Full Code of ChatGPTBox-dev/chatGPTBox for AI

master c236a4b12818 cached
227 files
910.5 KB
252.9k tokens
350 symbols
1 requests
Download .txt
Showing preview only (974K chars total). Download the full file or copy to clipboard to get everything.
Repository: ChatGPTBox-dev/chatGPTBox
Branch: master
Commit: c236a4b12818
Files: 227
Total size: 910.5 KB

Directory structure:
gitextract_4t6jkhck/

├── .eslintrc.json
├── .gitattributes
├── .github/
│   ├── CONTRIBUTING.md
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report---问题报告.md
│   │   └── feature-request---新功能请求.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── pr-tests.yml
│       ├── pre-release-build.yml
│       ├── scripts/
│       │   ├── update-coverage-badge.mjs
│       │   └── verify-search-engine-configs.mjs
│       ├── tagged-release.yml
│       └── verify-configs.yml
├── .gitignore
├── .nvmrc
├── .prettierignore
├── .prettierrc
├── AGENTS.md
├── CURRENT_CHANGE.md
├── LICENSE
├── README.md
├── README_IN.md
├── README_JA.md
├── README_TR.md
├── README_ZH.md
├── badges/
│   └── coverage.json
├── build.mjs
├── package.json
├── safari/
│   ├── appdmg.json
│   ├── build.sh
│   ├── export-options.plist
│   ├── project.patch
│   ├── project.pre.patch
│   └── project_developer.patch
├── src/
│   ├── _locales/
│   │   ├── de/
│   │   │   └── main.json
│   │   ├── en/
│   │   │   └── main.json
│   │   ├── es/
│   │   │   └── main.json
│   │   ├── fr/
│   │   │   └── main.json
│   │   ├── i18n-react.mjs
│   │   ├── i18n.mjs
│   │   ├── in/
│   │   │   └── main.json
│   │   ├── it/
│   │   │   └── main.json
│   │   ├── ja/
│   │   │   └── main.json
│   │   ├── ko/
│   │   │   └── main.json
│   │   ├── pt/
│   │   │   └── main.json
│   │   ├── resources.mjs
│   │   ├── ru/
│   │   │   └── main.json
│   │   ├── tr/
│   │   │   └── main.json
│   │   ├── zh-hans/
│   │   │   └── main.json
│   │   └── zh-hant/
│   │       └── main.json
│   ├── background/
│   │   ├── commands.mjs
│   │   ├── index.mjs
│   │   ├── menus.mjs
│   │   └── redact.mjs
│   ├── components/
│   │   ├── ConfirmButton/
│   │   │   └── index.jsx
│   │   ├── ConversationCard/
│   │   │   └── index.jsx
│   │   ├── ConversationItem/
│   │   │   └── index.jsx
│   │   ├── CopyButton/
│   │   │   └── index.jsx
│   │   ├── DecisionCard/
│   │   │   └── index.jsx
│   │   ├── DeleteButton/
│   │   │   └── index.jsx
│   │   ├── FeedbackForChatGPTWeb/
│   │   │   └── index.jsx
│   │   ├── FloatingToolbar/
│   │   │   └── index.jsx
│   │   ├── InputBox/
│   │   │   └── index.jsx
│   │   ├── MarkdownRender/
│   │   │   ├── Hyperlink.jsx
│   │   │   ├── Pre.jsx
│   │   │   ├── markdown-without-katex.jsx
│   │   │   └── markdown.jsx
│   │   ├── ReadButton/
│   │   │   └── index.jsx
│   │   ├── WebJumpBackNotification/
│   │   │   └── index.jsx
│   │   └── index.mjs
│   ├── config/
│   │   ├── index.mjs
│   │   └── language.mjs
│   ├── content-script/
│   │   ├── index.jsx
│   │   ├── menu-tools/
│   │   │   └── index.mjs
│   │   ├── selection-tools/
│   │   │   └── index.mjs
│   │   ├── site-adapters/
│   │   │   ├── arxiv/
│   │   │   │   └── index.mjs
│   │   │   ├── baidu/
│   │   │   │   └── index.mjs
│   │   │   ├── bilibili/
│   │   │   │   └── index.mjs
│   │   │   ├── brave/
│   │   │   │   └── index.mjs
│   │   │   ├── duckduckgo/
│   │   │   │   └── index.mjs
│   │   │   ├── followin/
│   │   │   │   └── index.mjs
│   │   │   ├── github/
│   │   │   │   └── index.mjs
│   │   │   ├── gitlab/
│   │   │   │   └── index.mjs
│   │   │   ├── index.mjs
│   │   │   ├── juejin/
│   │   │   │   └── index.mjs
│   │   │   ├── quora/
│   │   │   │   └── index.mjs
│   │   │   ├── reddit/
│   │   │   │   └── index.mjs
│   │   │   ├── stackoverflow/
│   │   │   │   └── index.mjs
│   │   │   ├── weixin/
│   │   │   │   └── index.mjs
│   │   │   ├── youtube/
│   │   │   │   └── index.mjs
│   │   │   └── zhihu/
│   │   │       └── index.mjs
│   │   └── styles.scss
│   ├── fonts/
│   │   └── styles.css
│   ├── hooks/
│   │   ├── use-clamp-window-size.mjs
│   │   ├── use-config.mjs
│   │   ├── use-theme.mjs
│   │   ├── use-window-size.mjs
│   │   └── use-window-theme.mjs
│   ├── manifest.json
│   ├── manifest.v2.json
│   ├── pages/
│   │   ├── IndependentPanel/
│   │   │   ├── App.jsx
│   │   │   ├── index.html
│   │   │   ├── index.jsx
│   │   │   └── styles.scss
│   │   └── styles.scss
│   ├── popup/
│   │   ├── Popup.jsx
│   │   ├── index.html
│   │   ├── index.jsx
│   │   ├── sections/
│   │   │   ├── AdvancedPart.jsx
│   │   │   ├── ApiModes.jsx
│   │   │   ├── FeaturePages.jsx
│   │   │   ├── GeneralPart.jsx
│   │   │   ├── ModulesPart.jsx
│   │   │   ├── SelectionTools.jsx
│   │   │   ├── SiteAdapters.jsx
│   │   │   └── import-data-cleanup.mjs
│   │   └── styles.scss
│   ├── rules.json
│   ├── services/
│   │   ├── apis/
│   │   │   ├── aiml-api.mjs
│   │   │   ├── azure-openai-api.mjs
│   │   │   ├── bard-web.mjs
│   │   │   ├── bing-web.mjs
│   │   │   ├── chatglm-api.mjs
│   │   │   ├── chatgpt-web.mjs
│   │   │   ├── claude-api.mjs
│   │   │   ├── claude-web.mjs
│   │   │   ├── custom-api.mjs
│   │   │   ├── deepseek-api.mjs
│   │   │   ├── moonshot-api.mjs
│   │   │   ├── moonshot-web.mjs
│   │   │   ├── ollama-api.mjs
│   │   │   ├── openai-api.mjs
│   │   │   ├── openai-token-params.mjs
│   │   │   ├── openrouter-api.mjs
│   │   │   ├── poe-web.mjs
│   │   │   ├── shared.mjs
│   │   │   └── waylaidwanderer-api.mjs
│   │   ├── clients/
│   │   │   ├── bard/
│   │   │   │   └── index.mjs
│   │   │   ├── bing/
│   │   │   │   ├── BingImageCreator.js
│   │   │   │   └── index.mjs
│   │   │   ├── claude/
│   │   │   │   └── index.mjs
│   │   │   └── poe/
│   │   │       ├── graphql/
│   │   │       │   ├── AddHumanMessageMutation.graphql
│   │   │       │   ├── AddMessageBreakMutation.graphql
│   │   │       │   ├── AutoSubscriptionMutation.graphql
│   │   │       │   ├── BioFragment.graphql
│   │   │       │   ├── ChatAddedSubscription.graphql
│   │   │       │   ├── ChatFragment.graphql
│   │   │       │   ├── ChatPaginationQuery.graphql
│   │   │       │   ├── ChatViewQuery.graphql
│   │   │       │   ├── DeleteHumanMessagesMutation.graphql
│   │   │       │   ├── HandleFragment.graphql
│   │   │       │   ├── LoginWithVerificationCodeMutation.graphql
│   │   │       │   ├── MessageAddedSubscription.graphql
│   │   │       │   ├── MessageDeletedSubscription.graphql
│   │   │       │   ├── MessageFragment.graphql
│   │   │       │   ├── MessageRemoveVoteMutation.graphql
│   │   │       │   ├── MessageSetVoteMutation.graphql
│   │   │       │   ├── SendVerificationCodeForLoginMutation.graphql
│   │   │       │   ├── ShareMessagesMutation.graphql
│   │   │       │   ├── SignupWithVerificationCodeMutation.graphql
│   │   │       │   ├── StaleChatUpdateMutation.graphql
│   │   │       │   ├── SummarizePlainPostQuery.graphql
│   │   │       │   ├── SummarizeQuotePostQuery.graphql
│   │   │       │   ├── SummarizeSharePostQuery.graphql
│   │   │       │   ├── UserSnippetFragment.graphql
│   │   │       │   ├── ViewerInfoQuery.graphql
│   │   │       │   ├── ViewerStateFragment.graphql
│   │   │       │   └── ViewerStateUpdatedSubscription.graphql
│   │   │       ├── index.mjs
│   │   │       └── websocket.js
│   │   ├── init-session.mjs
│   │   ├── local-session.mjs
│   │   └── wrappers.mjs
│   └── utils/
│       ├── change-children-font-size.mjs
│       ├── create-element-at-position.mjs
│       ├── crop-text.mjs
│       ├── ends-with-question-mark.mjs
│       ├── eventsource-parser.mjs
│       ├── fetch-bg.mjs
│       ├── fetch-sse.mjs
│       ├── get-client-position.mjs
│       ├── get-conversation-pairs.mjs
│       ├── get-core-content-text.mjs
│       ├── get-possible-element-by-query-selector.mjs
│       ├── index.mjs
│       ├── is-edge.mjs
│       ├── is-firefox.mjs
│       ├── is-mobile.mjs
│       ├── is-safari.mjs
│       ├── jwt-token-generator.mjs
│       ├── limited-fetch.mjs
│       ├── model-name-convert.mjs
│       ├── open-url.mjs
│       ├── parse-float-with-clamp.mjs
│       ├── parse-int-with-clamp.mjs
│       ├── set-element-position-in-viewport.mjs
│       ├── update-ref-height.mjs
│       └── wait-for-element-to-exist-and-select.mjs
└── tests/
    ├── setup/
    │   ├── browser-shim.mjs
    │   └── jsx-loader-hooks.mjs
    └── unit/
        ├── background/
        │   └── redact.test.mjs
        ├── config/
        │   ├── config-predicates.test.mjs
        │   └── user-config.test.mjs
        ├── content-script/
        │   └── selection-tools.test.mjs
        ├── helpers/
        │   ├── port.mjs
        │   └── sse-response.mjs
        ├── popup/
        │   └── import-data-cleanup.test.mjs
        ├── services/
        │   ├── apis/
        │   │   ├── azure-openai-api.test.mjs
        │   │   ├── claude-api.test.mjs
        │   │   ├── custom-api.test.mjs
        │   │   ├── openai-api-compat.test.mjs
        │   │   ├── openai-token-params.test.mjs
        │   │   ├── shared.test.mjs
        │   │   └── thin-adapters.test.mjs
        │   ├── handle-port-error.test.mjs
        │   ├── init-session.test.mjs
        │   ├── local-session.test.mjs
        │   └── wrappers-register.test.mjs
        ├── setup/
        │   └── browser-shim.test.mjs
        └── utils/
            ├── basic-guards.test.mjs
            ├── browser-detection.test.mjs
            ├── crop-text.test.mjs
            ├── eventsource-parser.test.mjs
            ├── fetch-sse.test.mjs
            ├── get-client-position.test.mjs
            ├── jwt-token-generator.test.mjs
            ├── model-name-convert.test.mjs
            └── set-element-position-in-viewport.test.mjs

================================================
FILE CONTENTS
================================================

================================================
FILE: .eslintrc.json
================================================
{
  "env": {
    "browser": true,
    "es2021": true
  },
  "extends": ["eslint:recommended", "plugin:react/recommended"],
  "overrides": [],
  "parserOptions": {
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "rules": {
    "react/react-in-jsx-scope": "off"
  },
  "ignorePatterns": ["build/**", "build.mjs", "src/utils/is-mobile.mjs"],
  "settings": {
    "react": {
      "version": "detect"
    }
  }
}


================================================
FILE: .gitattributes
================================================
src/services/clients/** linguist-vendored


================================================
FILE: .github/CONTRIBUTING.md
================================================
See https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Development&Contributing

================================================
FILE: .github/ISSUE_TEMPLATE/bug-report---问题报告.md
================================================
---
name: Bug report / 问题报告
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
**问题描述**
A clear and concise description of what the bug is.

**To Reproduce**
**如何复现**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
**期望行为**
A clear and concise description of what you expected to happen.

**Screenshots**
**截图说明**
If applicable, add screenshots to help explain your problem.

**Please complete the following information):**
**请补全以下内容**
 - OS: [e.g. Windows]
 - Browser: [e.g. chrome, safari]
 - Extension Version: [e.g. v2.0.2]

**Additional context**
**其他**
Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature-request---新功能请求.md
================================================
---
name: Feature request / 新功能请求
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
**新功能是否与解决某个问题相关, 请描述**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
**你期望的新功能实现方案**
A clear and concise description of what you want to happen.

**Additional context**
**其他**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
    commit-message:
      prefix: "chore"
      include: "scope"

================================================
FILE: .github/workflows/pr-tests.yml
================================================
name: pr-tests

on:
  pull_request:
    types:
      - "opened"
      - "reopened"
      - "synchronize"
    paths:
      - "src/**"
      - "build.mjs"
      - "tests/**"
      - "package.json"
      - "package-lock.json"
      - ".github/workflows/scripts/**"
      - ".github/workflows/pr-tests.yml"
  push:
    branches:
      - "master"
    paths:
      - "src/**"
      - "build.mjs"
      - "tests/**"
      - "package.json"
      - "package-lock.json"
      - ".github/workflows/scripts/**"
      - ".github/workflows/pr-tests.yml"

jobs:
  tests:
    runs-on: ubuntu-22.04
    permissions:
      contents: read

    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: 22
      - run: npm ci
      - run: npm run test:coverage
      - run: npm run lint
      - run: npm run build

  update_coverage_badge:
    if: github.event_name == 'push' && github.ref == 'refs/heads/master'
    needs: tests
    runs-on: ubuntu-22.04
    permissions:
      contents: write

    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v6
        with:
          node-version: 22
      - run: npm ci
      - run: npm run test:coverage
      - run: node .github/workflows/scripts/update-coverage-badge.mjs
      - name: Commit coverage badge
        run: |
          branch="${GITHUB_REF#refs/heads/}"
          max_retries=3

          if git diff --quiet -- badges/coverage.json; then
            echo "Coverage badge unchanged"
            exit 0
          fi

          git config user.name "github-actions[bot]"
          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
          git add badges/coverage.json
          git commit -m "Update coverage badge [skip ci]"

          for attempt in $(seq 1 "${max_retries}"); do
            echo "Attempt ${attempt}/${max_retries}: pushing coverage badge update to ${branch}"

            if git push origin "HEAD:${branch}"; then
              echo "Coverage badge push succeeded"
              exit 0
            fi

            if [ "${attempt}" -eq "${max_retries}" ]; then
              echo "::warning::Failed to push coverage badge after ${max_retries} attempts due to concurrent updates. Skipping without failing CI."
              exit 0
            fi

            echo "Push rejected. Fetching latest origin/${branch} and retrying with rebase..."
            if ! git fetch origin "${branch}"; then
              echo "::warning::Failed to fetch origin/${branch} while retrying coverage badge push. Skipping without failing CI."
              exit 0
            fi

            if ! git rebase "origin/${branch}"; then
              git rebase --abort || true
              echo "::warning::Rebase conflict while retrying coverage badge push. Skipping without failing CI."
              exit 0
            fi

            sleep $((attempt * 2))
          done


================================================
FILE: .github/workflows/pre-release-build.yml
================================================
name: pre-release
on:
  workflow_dispatch:
#  push:
#    branches:
#      - master
#    paths:
#      - "src/**"
#      - "!src/**/*.json"
#      - "build.mjs"
#    tags-ignore:
#      - "v*"

permissions:
  id-token: "write"
  contents: "write"

jobs:
  build_and_release:
    runs-on: ubuntu-22.04

    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: 22
          cache: 'npm'
          cache-dependency-path: '**/package-lock.json'
      - name: Detect Node version
        run: echo "NODE_VERSION=$(node -p 'process.versions.node')" >> $GITHUB_ENV
      - run: npm ci
      - name: Cache Webpack filesystem cache
        uses: actions/cache@v5
        with:
          path: |
            .cache/webpack
            node_modules/.cache/webpack
          key: ${{ runner.os }}-node${{ env.NODE_VERSION }}-webpack-${{ hashFiles('**/package-lock.json', 'build.mjs') }}
          restore-keys: |
            ${{ runner.os }}-node${{ env.NODE_VERSION }}-webpack-
      - run: npm run build

      - uses: josStorer/get-current-time@v2
        id: current-time
        with:
          format: YYYY_MMDD_HHmm

      - uses: actions/upload-artifact@v7
        with:
          name: Chromium_Build_${{ steps.current-time.outputs.formattedTime }}
          path: build/chromium/*

      - uses: actions/upload-artifact@v7
        with:
          name: Firefox_Build_${{ steps.current-time.outputs.formattedTime }}
          path: build/firefox/*

      - uses: actions/upload-artifact@v7
        with:
          name: Chromium_Build_WithoutKatex_${{ steps.current-time.outputs.formattedTime }}
          path: build/chromium-without-katex-and-tiktoken/*

      - uses: actions/upload-artifact@v7
        with:
          name: Firefox_Build_WithoutKatex_${{ steps.current-time.outputs.formattedTime }}
          path: build/firefox-without-katex-and-tiktoken/*

      - uses: marvinpinto/action-automatic-releases@v1.2.1
        with:
          repo_token: "${{ secrets.GITHUB_TOKEN }}"
          automatic_release_tag: "latest"
          prerelease: true
          title: "Development Build"
          files: |
            build/chromium.zip
            build/firefox.zip
            build/chromium-without-katex-and-tiktoken.zip
            build/firefox-without-katex-and-tiktoken.zip


================================================
FILE: .github/workflows/scripts/update-coverage-badge.mjs
================================================
import fs from 'node:fs'
import path from 'node:path'

const coverageSummaryPath = 'coverage/coverage-summary.json'
const badgePath = 'badges/coverage.json'

function getBadgeColor(percentage) {
  if (percentage >= 90) return 'brightgreen'
  if (percentage >= 80) return 'green'
  if (percentage >= 70) return 'yellowgreen'
  if (percentage >= 60) return 'yellow'
  if (percentage >= 50) return 'orange'
  return 'red'
}

function main() {
  if (!fs.existsSync(coverageSummaryPath)) {
    throw new Error(`Coverage summary file not found: ${coverageSummaryPath}`)
  }

  const summary = JSON.parse(fs.readFileSync(coverageSummaryPath, 'utf8'))
  const linesPercentage = Number(summary?.total?.lines?.pct)

  if (!Number.isFinite(linesPercentage)) {
    throw new Error('Unable to read lines coverage percentage from coverage summary')
  }

  const roundedPercentage = Number(linesPercentage.toFixed(2))
  const badge = {
    schemaVersion: 1,
    label: 'coverage',
    message: `${roundedPercentage}%`,
    color: getBadgeColor(roundedPercentage),
  }

  fs.mkdirSync(path.dirname(badgePath), { recursive: true })
  fs.writeFileSync(badgePath, JSON.stringify(badge, null, 2) + '\n')
  console.log(`Updated ${badgePath} with lines coverage ${roundedPercentage}%`)
}

main()


================================================
FILE: .github/workflows/scripts/verify-search-engine-configs.mjs
================================================
import { JSDOM } from 'jsdom'
import fetch, { Headers } from 'node-fetch'

const config = {
  google: {
    inputQuery: ["input[name='q']", "textarea[name='q']"],
    sidebarContainerQuery: ['#rhs'],
    appendContainerQuery: ['#rcnt'],
    resultsContainerQuery: ['#rso'],
  },
  bing: {
    inputQuery: ["[name='q']"],
    sidebarContainerQuery: ['#b_context'],
    appendContainerQuery: [],
    resultsContainerQuery: ['#b_results'],
  },
  yahoo: {
    inputQuery: ["input[name='p']"],
    sidebarContainerQuery: ['#right', '.Contents__inner.Contents__inner--sub'],
    appendContainerQuery: ['#cols', '#contents__wrap'],
    resultsContainerQuery: [
      '#main-algo',
      '.searchCenterMiddle',
      '.Contents__inner.Contents__inner--main',
      '#contentsInner',
    ],
  },
  duckduckgo: {
    inputQuery: ["input[name='q']"],
    sidebarContainerQuery: ['.js-react-sidebar', '.react-results--sidebar'],
    appendContainerQuery: ['#links_wrapper'],
    resultsContainerQuery: ['.react-results--main'],
  },
  startpage: {
    inputQuery: ["input[name='query']"],
    sidebarContainerQuery: ['#sidebar'],
    appendContainerQuery: [],
    resultsContainerQuery: ['#main'],
  },
  baidu: {
    inputQuery: ["input[id='kw']"],
    sidebarContainerQuery: ['#content_right'],
    appendContainerQuery: ['#container'],
    resultsContainerQuery: ['#content_left', '#results'],
  },
  kagi: {
    inputQuery: ["input[name='q']", "textarea[name='q']"],
    sidebarContainerQuery: ['.right-content-box'],
    appendContainerQuery: ['#_0_app_content'],
    resultsContainerQuery: ['#main', '#app'],
  },
  yandex: {
    inputQuery: ["input[name='text']"],
    sidebarContainerQuery: ['#search-result-aside'],
    appendContainerQuery: [],
    resultsContainerQuery: ['#search-result'],
  },
  naver: {
    inputQuery: ["input[name='query']"],
    sidebarContainerQuery: ['#main_pack'],
    appendContainerQuery: ['#content'],
    resultsContainerQuery: ['#main_pack', '#ct'],
  },
  brave: {
    inputQuery: ["input[name='q']"],
    sidebarContainerQuery: ['.sidebar'],
    appendContainerQuery: [],
    resultsContainerQuery: ['#results'],
  },
  searx: {
    inputQuery: ["input[name='q']"],
    sidebarContainerQuery: ['#sidebar_results', '#sidebar'],
    appendContainerQuery: [],
    resultsContainerQuery: ['#urls', '#main_results', '#results'],
  },
  ecosia: {
    inputQuery: ["input[name='q']"],
    sidebarContainerQuery: ['.sidebar.web__sidebar'],
    appendContainerQuery: ['#main'],
    resultsContainerQuery: ['.mainline'],
  },
  neeva: {
    inputQuery: ["input[name='q']"],
    sidebarContainerQuery: ['.result-group-layout__stickyContainer-iDIO8'],
    appendContainerQuery: ['.search-index__searchHeaderContainer-2JD6q'],
    resultsContainerQuery: ['.result-group-layout__component-1jzTe', '#search'],
  },
}

const urls = {
  google: [
    /*'https://www.google.com/search?q=hello'*/
  ],
  bing: ['https://www.bing.com/search?q=hello'],
  yahoo: [
    /*'https://search.yahoo.com/search?p=hello', */ 'https://search.yahoo.co.jp/search?p=hello',
  ],
  duckduckgo: [],
  startpage: [], // need redirect and post https://www.startpage.com/do/search?query=hello
  baidu: ['https://www.baidu.com/s?wd=hello'],
  kagi: [], // need login https://kagi.com/search?q=hello
  yandex: [], // need cookie https://yandex.com/search/?text=hello
  naver: ['https://search.naver.com/search.naver?query=hello'],
  brave: [],
  searx: [
    /*'https://searx.tiekoetter.com/search?q=hello'*/
  ],
  ecosia: [], // unknown verify method https://www.ecosia.org/search?q=hello
  neeva: [], // unknown verify method(FetchError: maximum redirect reached) https://neeva.com/search?q=hello
  presearch: [],
}

const commonHeaders = {
  Accept:
    'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
  Connection: 'keep-alive',
  'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7', // for baidu
}

const desktopHeaders = new Headers({
  'User-Agent':
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/108.0.1462.76',
  ...commonHeaders,
})

const mobileHeaders = {
  'User-Agent':
    'Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Mobile Safari/537.36 Edg/108.0.1462.76',
  ...commonHeaders,
}

const desktopQueryNames = [
  'inputQuery',
  'sidebarContainerQuery',
  'appendContainerQuery',
  'resultsContainerQuery',
]

const mobileQueryNames = ['inputQuery', 'resultsContainerQuery']

let errors = ''

async function verify(errorTag, urls, headers, queryNames) {
  await Promise.all(
    Object.entries(urls).map(([siteName, urlArray]) =>
      Promise.all(
        urlArray.map((url) =>
          fetch(url, {
            method: 'GET',
            headers: headers,
          })
            .then((response) => response.text())
            .then((text) => {
              const dom = new JSDOM(text)
              for (const queryName of queryNames) {
                const queryArray = config[siteName][queryName]
                if (queryArray.length === 0) continue

                let foundQuery
                for (const query of queryArray) {
                  const element = dom.window.document.querySelector(query)
                  if (element) {
                    foundQuery = query
                    break
                  }
                }
                if (foundQuery) {
                  console.log(`${siteName} ${url} ${queryName}: ${foundQuery} passed`)
                } else {
                  const error = `${siteName} ${url} ${queryName} failed`
                  errors += errorTag + error + '\n'
                }
              }
            })
            .catch((error) => {
              errors += errorTag + error + '\n'
            }),
        ),
      ),
    ),
  )
}

async function main() {
  console.log('Verify desktop search engine configs:')
  await verify('desktop: ', urls, desktopHeaders, desktopQueryNames)
  console.log('\nVerify mobile search engine configs:')
  await verify('mobile: ', urls, mobileHeaders, mobileQueryNames)

  if (errors.length > 0) throw new Error('\n' + errors)
  else console.log('\nAll passed')
}

main()


================================================
FILE: .github/workflows/tagged-release.yml
================================================
name: tagged-release
on:
  push:
    tags:
      - "v*"

permissions:
  id-token: "write"
  contents: "write"
env:
  GH_TOKEN: ${{ github.token }}

jobs:
  build_and_release:
    runs-on: macos-14

    steps:
      - run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
      - uses: actions/checkout@v6
        with:
          ref: master

      - name: Update manifest.json version
        uses: jossef/action-set-json-field@v2.2
        with:
          file: src/manifest.json
          field: version
          value: ${{ env.VERSION }}

      - name: Update manifest.v2.json version
        uses: jossef/action-set-json-field@v2.2
        with:
          file: src/manifest.v2.json
          field: version
          value: ${{ env.VERSION }}

      - name: Push files
        continue-on-error: true
        run: |
          git config --global user.email "github-actions[bot]@users.noreply.github.com"
          git config --global user.name "github-actions[bot]"
          git commit -am "release v${{ env.VERSION }}"
          git push

      - run: |
          gh release create ${{github.ref_name}} -d -F CURRENT_CHANGE.md -t ${{github.ref_name}}

      - uses: actions/setup-node@v6
        with:
          node-version: 22
      - run: npm ci

      - uses: actions/setup-python@v6
        with:
          python-version: '3.10' # for appdmg
      - uses: maxim-lobanov/setup-xcode@v1
        with:
          xcode-version: 16.2
      - run: sed -i '' "s/0.0.0/${{ env.VERSION }}/g" safari/project.pre.patch
      - run: sed -i '' "s/0.0.0/${{ env.VERSION }}/g" safari/project.patch
      - run: npm run build:safari

      - run: |
          gh release upload ${{github.ref_name}} build/chromium.zip
          gh release upload ${{github.ref_name}} build/firefox.zip
          gh release upload ${{github.ref_name}} build/safari.dmg
          gh release upload ${{github.ref_name}} build/chromium-without-katex-and-tiktoken.zip
          gh release upload ${{github.ref_name}} build/firefox-without-katex-and-tiktoken.zip

      - run: |
          gh release edit ${{github.ref_name}} --draft=false


================================================
FILE: .github/workflows/verify-configs.yml
================================================
name: verify-configs
on:
  workflow_dispatch:
  schedule:
    - cron: "0 6 * * *"

jobs:
  verify_configs:
    runs-on: ubuntu-22.04

    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: 22
      - run: npm ci
      - run: npm run verify


================================================
FILE: .gitignore
================================================
.idea/
.vscode/
node_modules/
build/
.coverage/
coverage/
.DS_Store
*.zip


================================================
FILE: .nvmrc
================================================
22


================================================
FILE: .prettierignore
================================================
build/
src/manifest.json
src/manifest.v2.json

================================================
FILE: .prettierrc
================================================
{
  "printWidth": 100,
  "semi": false,
  "tabWidth": 2,
  "singleQuote": true,
  "trailingComma": "all",
  "bracketSpacing": true,
  "overrides": [
    {
      "files": ".prettierrc",
      "options": {
        "parser": "json"
      }
    }
  ]
}


================================================
FILE: AGENTS.md
================================================
# ChatGPTBox - Browser Extension

ChatGPTBox is a cross-platform browser extension that deeply integrates ChatGPT and other AI models into web browsing. The extension provides chat dialogs, selection tools, site-specific adapters, and AI-powered features across the web.

Always reference these instructions first and fall back to search or bash commands only when you encounter unexpected information that does not match the info here.

## Working Effectively

### Bootstrap and Build

- Install dependencies: `npm ci` -- npm audit warnings may appear; for development-only dependencies they generally do not affect the shipped extension. Review and address runtime-impacting advisories separately.
- Development build: `npm run dev` -- runs webpack in watch mode. Do not kill mid-compilation, but stop gracefully when switching branches or after dependency/config changes, then restart to avoid stale watchers and inconsistent state.
- Production build: `npm run build` -- Avoid force-killing mid-bundle; stop, fix, then rebuild.
  See "Time Expectations" and "Build Issues" for the hung-build policy and recovery steps.
- Analyze bundle: `npm run analyze` -- Inspects the size of webpack output files.
- Format code: `npm run pretty` -- uses Prettier to format all JS/JSX/CSS files. Run this before linting.
- Lint code: `npm run lint` -- uses ESLint.
- Safari build: `npm run build:safari` (see Platform-Specific Instructions for details)

### Build Performance Options

- BUILD_PARALLEL: Toggle parallel build of production variants
  - Default: on (parallel). Set to `0` to run sequentially (lower CPU/IO spikes on low-core machines)
- BUILD_THREAD / BUILD_THREAD_WORKERS: Control Babel parallelism via thread-loader
  - Default: threads enabled in dev/prod; workers = CPU cores
  - Set `BUILD_THREAD=0` to disable; set `BUILD_THREAD_WORKERS=<n>` to override worker count
- BUILD_CACHE_COMPRESSION: Webpack filesystem cache compression
  - Default: `0` (no compression) for faster warm builds on CPU-bound SSD machines
  - Options: `0|false|none`, `gzip` (or `brotli` if explicitly desired)
  - Affects only `.cache/webpack` size/speed; does not change final artifacts
  - Note: Babel loader cache uses its own compression setting (currently disabled for speed) and is independent of BUILD_CACHE_COMPRESSION
- BUILD_WATCH_ONCE (dev): When set, `npm run dev` runs a single build and exits (useful for timing)
- BUILD_POOL_TIMEOUT: Override thread-loader production pool timeout (ms)
  - Default: `2000`. Increase if workers recycle too aggressively on slow machines/CI
- BUILD_RESOLVE_SYMLINKS: When set to `1`/`true`, re-enable Webpack symlink resolution for `npm link`/pnpm workspace development. Default is `false` to improve performance and ensure consistent module identity (avoids duplicate module instances)
- Source maps (dev): Dev builds emit external `.map` files next to JS bundles for CSP-safe debugging; production builds disable source maps

Performance defaults: esbuild handles JS/CSS minification. In development, CSS is injected via style-loader; in production, CSS is extracted via MiniCssExtractPlugin. Thread-loader is enabled by default in both dev and prod.

### Build Output Structure

Production build creates multiple variants in `build/` directory:

- `chromium/` - Chromium-based browsers (Chrome, Edge) with full features
- `firefox/` - Firefox with manifest v2
- `chromium-without-katex-and-tiktoken/` - Minimal build without math rendering and token encoding
- `firefox-without-katex-and-tiktoken/` - Minimal Firefox build without math rendering and token encoding
- Distribution artifacts:
  - Chromium: `build/chromium.zip`
  - Firefox: `build/firefox.zip`
  - Safari: `Fission - ChatBox.app` and `safari.dmg` (see Safari Build section for details)

## Architecture Overview

The project uses Preact (for React-like components), SCSS (for styling), and Webpack 5 (for bundling).

### Key Components

- **Content Script** (`src/content-script/index.jsx`) - Injected into all web pages, provides main chat functionality
- **Background Script** (`src/background/index.mjs`) - Handles browser APIs and cross-page communication
- **Popup** (`src/popup/`) - Extension popup interface accessible via browser toolbar
- **Independent Panel** (`src/pages/IndependentPanel/`) - Standalone chat page and side panel
- **Site Adapters** (`src/content-script/site-adapters/`) - Custom integrations for specific websites (Reddit, GitHub, YouTube, etc.)
- **Selection Tools** (`src/content-script/selection-tools/`) - Text selection features (translate, summarize, explain, etc.)

### Manifests

- `src/manifest.json` - Manifest v3 for Chromium browsers (Chrome, Edge, Opera, etc.)
- `src/manifest.v2.json` - Manifest v2 for Firefox (current status; future MV3 migration may change this)
  - Background runs as service worker (MV3) vs background page (MV2)
  - Different permission models between manifest versions

## Testing and Validation

### Manual Browser Extension Testing (CRITICAL)

This browser extension includes automated unit tests, but manual browser extension testing is still essential:

1. **Load Extension in Browser:**
   - Chrome: Go to `chrome://extensions/`, enable Developer Mode, click "Load unpacked", then select the folder `build/chromium/` (the folder must contain `manifest.json`).
   - Firefox: Go to `about:debugging#/runtime/this-firefox`, click "Load Temporary Add-on", then select the `manifest.json` file inside `build/firefox/` (do not select the folder directly). Note: Temporary (unsigned) add-ons are removed on browser restart; reload them via the same "This Firefox" page after every restart, and some environments with enterprise policies may block loading from file.
   - **Important**: Extension files cannot be tested by serving them via HTTP server - they must be loaded as a proper browser extension.

2. **Core Functionality Tests:**
   - Press `Ctrl+B` (Windows/Linux) or `⌘+B` (macOS) to open the chat dialog on any webpage
   - Select text on a page, verify selection tools appear
   - Right-click and verify "Ask ChatGPT" context menu appears
   - Click extension icon to open popup
   - Press `Ctrl+Shift+H` (Windows/Linux) or `⌘+Shift+H` (macOS) to open the independent conversation page

3. **Site Integration Tests:**
   - Visit YouTube.com, verify video summary features work
   - Visit Reddit.com, verify ChatGPT integration appears in sidebar
   - Visit GitHub.com, verify code analysis features work
   - Visit Google.com search results, verify ChatGPT responses appear

4. **Configuration Tests:**
   - Open extension popup, navigate through tabs (General, Feature Pages, Modules > Selection Tools, Modules > Sites, Advanced)
   - Test API mode switching (Web API vs OpenAI API) under Modules > API Modes
   - If using Web APIs, ensure you are signed in to the provider in the same browser profile; if using API Keys, configure valid keys in settings
   - Verify language settings work

Debugging tips:

- Inspect background Service Worker, page DevTools for content scripts, and use "Inspect popup" for the popup UI
- After rebuilds, reload the extension and refresh the page to re‑inject content scripts

### Build Validation

Ensure these files exist in `build/chromium/` after successful build:

- `manifest.json` (contains proper extension metadata)
- `background.js` (service worker bundle)
- `content-script.js` (main functionality)
- `content-script.css` (styling)
- `popup.html` and `popup.js` (popup interface)
- `IndependentPanel.html` and `IndependentPanel.js` (standalone chat page)
- `shared.js` (shared vendor/runtime; size varies by environment and dependencies)
- `logo.png` (extension icon)
- `rules.json` (declarative net request rules)

Bundle sizes are approximate and not validation criteria.

### Verify Script Limitations

- `npm run verify` tests search engine configurations by attempting to fetch search results from external search engines (Bing, Yahoo, Baidu, Naver) to validate that the site adapters can parse and handle real responses.
- **Successful validation**: For each search engine, the script expects to receive a valid HTTP response (status 200) and to successfully extract and parse search results using the corresponding site adapter. If the adapter can parse the expected data structure from the response, the test is considered a pass.
- **Expected failure modes**: In sandboxed or CI environments, the script may fail due to network restrictions (e.g., DNS errors, timeouts, connection refused), HTTP errors (e.g., 403, 429, 503), or changes in the search engine's response format. These failures are expected and do **not** indicate build problems.
- If you see network or HTTP errors during `npm run verify`, you can safely ignore them unless you are specifically testing or updating site adapter logic.

Usage notes:

- Default checks target: `https://www.bing.com/search?q=hello`, `https://search.yahoo.co.jp/search?p=hello`, `https://www.baidu.com/s?wd=hello`, `https://search.naver.com/search.naver?query=hello`
- Optional engines (may be blocked by region or anti-bot measures): Google, DuckDuckGo, Brave, Searx.
- Troubleshooting: If a site fails, try adjusting `Accept-Language`/`User-Agent` headers in the script, update the site's selector arrays with ordered fallbacks, or temporarily reduce the test to a single URL while iterating.

## Development Workflow

### Code Style, Quality, and File Organization

- ALWAYS run `npm run lint` before committing - CI will fail otherwise
- ALWAYS run `npm run pretty` to format code consistently
- ESLint configuration in `.eslintrc.json` enforces React/JSX standards
- Prettier configuration in `.prettierrc` handles formatting (100 char width, no semicolons, single quotes, trailing commas)

✅ Good: `import Browser from 'webextension-polyfill'` (single quotes, no semicolon)
❌ Bad: `import Browser from "webextension-polyfill";` (double quotes, semicolon)

- Naming conventions: component directories use PascalCase; feature folders use kebab-case; entry files are typically `index.jsx` or `index.mjs`
- Avoid heavy dependencies; if necessary, justify and keep bundle size under control

**Pre-commit hooks automatically:**

1. Run prettier formatting
2. Stage formatted files
3. Run lint checks

**Key file locations:**

- Configuration: `src/config/index.mjs`
- API integrations: `src/services/apis/`
- Localization: `src/_locales/`
- UI components: `src/components/`
- Utilities: `src/utils/`

### Commits & PRs

- Keep changes minimal and focused. Avoid unrelated refactors in the same PR.
- Commit subject: imperative, capitalize first word; separate subject/body with a blank line; wrap at ~72 characters; explain what and why.
- PRs: link related issues, summarize scope/behavior changes; include screenshots for UI changes.
- Note i18n updates in PR description when `src/_locales/` changes.
- If any validation step is skipped, document the reason and the skipped check(s) in the PR description (see `Critical Validation Steps` below).

### Directory Structure

```text
src/
├── background/             # Background script/service worker
├── components/             # Reusable UI components
├── config/                 # Configuration management
├── content-script/         # Main content script and features
│   ├── site-adapters/      # Website-specific integrations
│   ├── selection-tools/    # Text selection features
│   └── menu-tools/         # Context menu features
├── pages/IndependentPanel/ # Standalone chat page
├── popup/                  # Extension popup
├── services/               # API clients and wrappers
└── utils/                  # Helper functions
```

## Platform-Specific Instructions

### Safari Build (macOS Only)

- Run `npm run build:safari` (requires macOS with Xcode installed)
- Creates `Fission - ChatBox.app` bundle and `safari.dmg` installer
- Uses `safari/build.sh` script with platform-specific patches

### Cross-Browser Compatibility

- Uses `webextension-polyfill` for API compatibility

## Security & Privacy

- Do not commit secrets, API keys, or user data
- Keep manifest permissions minimal and justify any additions
- Centralize network/API logic under `src/services/apis/` and keep endpoints auditable

## Localization

- Source of truth: `src/_locales/en/main.json`; do not change existing keys (only add new ones)
- Add new strings to `en/main.json` first, then propagate to other locales
- Register new locales in `src/_locales/resources.mjs`
- Preserve placeholders and product names; keep punctuation/quotes intact
- For Traditional Chinese (Taiwan), use `src/_locales/zh-hant/main.json` and avoid zh‑CN terms

## AI Model Support

The extension supports multiple AI providers:

- **Web (cookie-based)**: ChatGPT (Web), Claude (Web), Kimi.Moonshot (Web), Bing (Web), Bard (Web), Poe (Web)
- **APIs (key-based)**: OpenAI (API), Azure OpenAI (API), Anthropic (Claude API), OpenRouter (API), AI/ML (API), DeepSeek (API), Ollama (local), ChatGLM (API), Waylaidwanderer (API), Kimi.Moonshot (API)
- **Custom/self-hosted**: Alternative endpoints and self-hosted backends

## Troubleshooting

### Build Issues

- Build failures: Check Node.js version (requires Node 22+), clear caches and rebuild.
  - macOS/Linux: `rm -rf node_modules && npm ci && rm -rf node_modules/.cache build/ dist/`
  - Windows (PowerShell): `Remove-Item -Recurse -Force node_modules, build, dist; if (Test-Path node_modules\.cache) { Remove-Item -Recurse -Force node_modules\.cache }; npm ci`
- "Module not found" errors: Usually indicate missing `npm ci`

### Runtime Issues

- Extension not loading: Check console for manifest errors
- API not working: Verify browser has required permissions and cookies
- Selection tools not appearing: Check if content script loaded correctly

### Common Development Tasks

- Adding new site adapter: Create new file in `src/content-script/site-adapters/`, register it in `src/content-script/site-adapters/index.mjs`, keep selectors minimal with feature detection, and verify on Chromium/Firefox
- Adding new selection tool: Modify `src/content-script/selection-tools/`, keep UI and logic separate, and reuse helpers in `src/utils/`
- Updating API integration: Modify files in `src/services/apis/`
- Adding new UI component: Create in `src/components/`

**Note:** Ask before deleting/renaming files, modifying build config/manifests, or making changes that affect multiple site adapters. If the user explicitly requests one of these changes, proceed and document scope and risk in the current workflow handoff output, and in the PR summary when applicable.

## Time Expectations

- Do not interrupt builds or long-running commands unless they appear hung or unresponsive.
- `npm ci`: ~30 seconds
- `npm run build`: ~35 seconds (measured). Set timeout to 5-10 minutes for system variations.
- `npm run dev`: ~15 seconds initial build, then watches for changes; use Ctrl+C to stop when switching branches or after config/dependency changes.
- `npm run lint`: ~5 seconds
- Manual extension testing: 5-10 minutes for thorough validation
- Safari build: 2-5 minutes (macOS only)

## Critical Validation Steps

1. General changes (any change not covered by Step 2 or Step 3): run `npm test` and `npm run build`, verify expected build artifacts, and run manual browser smoke tests. If changes include `safari/**`, also run `npm run build:safari` on macOS. If macOS is unavailable for those changes, document the skip reason in PR validation notes.
2. Behavior-adjacent localization changes (`src/_locales/**` only): run `npm run build` and manual browser smoke tests. Use this step only when all changed files are under `src/_locales/**`.
3. Docs-only changes (`*.md`, `screenshots/**`): build/manual browser tests may be skipped, but the PR description must include `Validation skipped: docs/screenshots-only change; no runtime files touched.`
4. If changes span multiple categories, apply the strictest applicable step (runtime > localization > docs/screenshots); when in doubt, treat the change as runtime-impacting and execute the full validation flow.

---

Most of this document was generated by AI and reviewed under human supervision. If you find any clear errors while using it, please submit corrections with supporting evidence where possible.


================================================
FILE: CURRENT_CHANGE.md
================================================
Long time no see — ChatGPTBox is back! Nearly every feature that had broken due to page updates or API changes has been fixed, and we’ve also introduced some new features.

Over the past year the LLM landscape has shifted dramatically, and the key players are now fairly clear. Regarding ChatGPTBox’s free web APIs, some providers are still actively trying to block reverse-engineering, while others remain open. At the moment, ChatGPT, Claude, and Kimi are still open, so we’ll keep maintaining the related web free APIs. The web APIs for Bing and Gemini, however, will no longer be supported; if you need some reverse-engineering web apis, please check out the work of this organization: https://github.com/LLM-Red-Team.

As OpenRouter has consistently offered stable and affordable APIs, we’ve now added direct option support for it — no need to rely on custom mode and manually fill in the API URL.

During this period, countless AI projects have exploded onto the scene and just as many have quietly disappeared. I’ve been tied up with various non-public projects and have neglected ChatGPTBox, while also pondering how to keep it vibrant.

I have to admit that when ChatGPTBox was first created, many decisions and code designs were rather hasty and not very modern. Without much forethought, I made choices that now make it inconvenient to add new features.

I’m currently rewriting ChatGPTBox from scratch using the WXT framework while ensuring full backward compatibility with old data. This will take a considerable amount of time, but I’ll keep pushing forward. I also have some commercialization ideas for ChatGPTBox; of course only server-related features would be charged, while all web APIs and user Api Key features will remain completely free, and the project will stay open-source under the MIT license.

As I’m simultaneously in charge of several other non-public projects, I can’t promise when the rewrite will be finished, but I’ll keep making steady progress. In the meantime, I’ll continue to fix major issues in the current version of ChatGPTBox.

## Changes

### Features

- add support for openRouter, AI/ML and DeepSeek api (previously required filling in the URL via the custom model option)
- a new option has been added to the general settings to disable cropText, ensuring the full input tokens are always passed. This can improve summarization on sites like YouTube, but note that you should only disable cropText when using a model with a sufficiently long context.
- <img width="300" src="https://github.com/user-attachments/assets/455931d6-8a73-4cdf-88a6-d4dcff53ecd7"/>
- reasoning model renderer support
- <img width="420" src="https://github.com/user-attachments/assets/1951cc7e-d12a-4cc2-8f7f-826603bbf884" />

### Improvements
- add a range of new models recently made available by various AI providers
- significantly improve the prompt templates for built-in tools. Great thanks to @PeterDaveHello 
- update and enhance API clients (including Claude, ChatGLM, and Kimi.Moonshot) that had become unavailable or unstable due to recent policy changes and adjustments by AI providers
- increase the default input and response limits, as current LLMs generally support longer contexts
- improve kimi.moonshot support and add more available models like k2, kimi-latest, k1.5, k1.5-thinking
- improve google search sidebar

### Fixes
- fix the issue where YouTube subtitles could not be fetched and the video summarization feature became unavailable due to the recent introduction of the "pot" parameter by YouTube
- avoid crash when readability parser returns null (#865) @PeterDaveHello 
- fix the issue where kimi web functionality became unstable due to changes in the page and domain
- fix an issue where the selected model might be not displayed correctly due to inconsistent key ordering in JSON.stringify
- fix the issue of abnormal subtitle retrieval caused by changes to Bilibili API

### Chores
- update adapters support for startpage, kagi, naver, wechat, juejin
- update dependencies to mitigate security vulnerabilities @PeterDaveHello 
- update default configs
- since ChatGPT has relaxed the web API request restrictions, it is no longer necessary to simulate input to retrieve data (#869)
- update verify-search-engine-configs.mjs


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2022 josStorer
Copyright (c) 2022 wong2

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
<p align="center">
    <img src="./src/logo.png">
</p>

<h1 align="center">ChatGPT Box</h1>

<div align="center">

Deep ChatGPT integrations in your browser, completely for free.

[![license][license-image]][license-url]
[![release][release-image]][release-url]
[![size](https://img.shields.io/badge/minified%20size-390%20kB-blue)][release-url]
[![verfiy][verify-image]][verify-url]
[![coverage][coverage-image]][coverage-url]

English &nbsp;&nbsp;|&nbsp;&nbsp; [Indonesia](README_IN.md) &nbsp;&nbsp;|&nbsp;&nbsp; [简体中文](README_ZH.md) &nbsp;&nbsp;|&nbsp;&nbsp; [日本語](README_JA.md) &nbsp;&nbsp;|&nbsp;&nbsp; [Türkçe](README_TR.md)

### Install

[![Chrome][Chrome-image]][Chrome-url]
[![Edge][Edge-image]][Edge-url]
[![Firefox][Firefox-image]][Firefox-url]
[![Safari][Safari-image]][Safari-url]
[![Android][Android-image]][Android-url]
[![Github][Github-image]][Github-url]

[Guide](https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Guide) &nbsp;&nbsp;|&nbsp;&nbsp; [Preview](#Preview) &nbsp;&nbsp;|&nbsp;&nbsp; [Development&Contributing][dev-url] &nbsp;&nbsp;|&nbsp;&nbsp; [Video Demonstration](https://www.youtube.com/watch?v=E1smDxJvTRs) &nbsp;&nbsp;|&nbsp;&nbsp; [Credit](#Credit)

[dev-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Development&Contributing

[license-image]: http://img.shields.io/badge/license-MIT-blue.svg

[license-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/blob/master/LICENSE

[release-image]: https://img.shields.io/github/release/ChatGPTBox-dev/chatGPTBox.svg

[release-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/releases/latest

[verify-image]: https://github.com/ChatGPTBox-dev/chatGPTBox/workflows/verify-configs/badge.svg

[verify-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/actions/workflows/verify-configs.yml

[coverage-image]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/ChatGPTBox-dev/chatGPTBox/master/badges/coverage.json

[coverage-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/actions/workflows/pr-tests.yml

[Chrome-image]: https://img.shields.io/badge/-Chrome-brightgreen?logo=google-chrome&logoColor=white

[Chrome-url]: https://chrome.google.com/webstore/detail/chatgptbox/eobbhoofkanlmddnplfhnmkfbnlhpbbo

[Edge-image]: https://img.shields.io/badge/-Edge-blue?logo=microsoft-edge&logoColor=white

[Edge-url]: https://microsoftedge.microsoft.com/addons/detail/fission-chatbox-best/enjmfilpkbbabhgeoadmdpjjpnahkogf

[Firefox-image]: https://img.shields.io/badge/-Firefox-orange?logo=firefox-browser&logoColor=white

[Firefox-url]: https://addons.mozilla.org/firefox/addon/chatgptbox/

[Safari-image]: https://img.shields.io/badge/-Safari-blue?logo=safari&logoColor=white

[Safari-url]: https://apps.apple.com/app/fission-chatbox/id6446611121

[Android-image]: https://img.shields.io/badge/-Android-brightgreen?logo=android&logoColor=white

[Android-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Install#install-to-android

[Github-image]: https://img.shields.io/badge/-Github-black?logo=github&logoColor=white

[Github-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Install

</div>

## News

- This extension does **not** collect your data. You can verify it by conducting a global search for `fetch(` and `XMLHttpRequest(` in the code to find all network request calls. The amount of code is not much, so it's easy to do that.

- This tool will not transmit any data to ChatGPT unless you explicitly ask it to. By default, the extension must be activated manually. It will only send a request to ChatGPT if you specifically click "Ask ChatGPT" or trigger the selection floating tools — and this is applicable only when you're using GPT API modes. (issue #407)

- You can use projects like https://github.com/BerriAI/litellm / https://github.com/songquanpeng/one-api to convert LLM APIs into OpenAI format and use them in conjunction with ChatGPTBox's `Custom Model` mode

- You can also use [Ollama](https://github.com/ChatGPTBox-dev/chatGPTBox/issues/616#issuecomment-1975186467) / https://openrouter.ai/docs#models with ChatGPTBox's `Custom Model` mode

## ✨ Features

- 🌈 Call up the chat dialog box on any page at any time. (<kbd>Ctrl</kbd>+<kbd>B</kbd>)
- 📱 Support for mobile devices.
- 📓 Summarize any page with right-click menu. (<kbd>Alt</kbd>+<kbd>B</kbd>)
- 📖 Independent conversation page. (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>H</kbd>)
- 🔗 Multiple API support (Web API for Free and Plus users, GPT-3.5, GPT-4, Claude, New Bing, Moonshot, Self-Hosted, Azure etc.).
- 📦 Integration for various commonly used websites (Reddit, Quora, YouTube, GitHub, GitLab, StackOverflow, Zhihu, Bilibili). (Inspired by [wimdenherder](https://github.com/wimdenherder))
- 🔍 Integration to all mainstream search engines, and custom queries to support additional sites.
- 🧰 Selection tool and right-click menu to perform various tasks, such as translation, summarization, polishing,
  sentiment analysis, paragraph division, code explain and queries.
- 🗂️ Static cards support floating chat boxes for multi-branch conversations.
- 🖨️ Easily save your complete chat records or copy them partially.
- 🎨 Powerful rendering support, whether for code highlighting or complex mathematical formulas.
- 🌍 Language preference support.
- 📝 Custom API address support.
- ⚙️ All site adaptations and selection tools(bubble) can be freely switched on or off, disable modules you don't need.
- 💡 Selection tools and site adaptation are easy to develop and extend, see the [Development&Contributing][dev-url]
  section.
- 😉 Chat to improve the answer quality.

## Preview

<div align="center">

**Search Engine Integration, Floating Windows, Conversation Branches**

![preview_google_floatingwindow_conversationbranch](screenshots/preview_google_floatingwindow_conversationbranch.jpg)

**Integration with Commonly Used Websites, Selection Tools**

![preview_reddit_selectiontools](screenshots/preview_reddit_selectiontools.jpg)

**Independent Conversation Page**

![preview_independentpanel](screenshots/preview_independentpanel.jpg)

**Git Analysis, Right Click Menu**

![preview_github_rightclickmenu](screenshots/preview_github_rightclickmenu.jpg)

**Video Summary**

![preview_youtube](screenshots/preview_youtube.jpg)

**Mobile Support**

![image](https://user-images.githubusercontent.com/13366013/225529110-9221c8ce-ad41-423e-b6ec-097981e74b66.png)

**Settings**

![preview_settings](screenshots/preview_settings.jpg)

</div>

## Credit

This project is based on one of my other repositories, [josStorer/chatGPT-search-engine-extension](https://github.com/josStorer/chatGPT-search-engine-extension)

[josStorer/chatGPT-search-engine-extension](https://github.com/josStorer/chatGPT-search-engine-extension) is forked
from [wong2/chat-gpt-google-extension](https://github.com/wong2/chat-gpt-google-extension) (I learned a lot from that)
and detached since 14 December of 2022

[wong2/chat-gpt-google-extension](https://github.com/wong2/chat-gpt-google-extension) is inspired
by [ZohaibAhmed/ChatGPT-Google](https://github.com/ZohaibAhmed/ChatGPT-Google) ([upstream-c54528b](https://github.com/wong2/chatgpt-google-extension/commit/c54528b0e13058ab78bfb433c92603db017d1b6b))


================================================
FILE: README_IN.md
================================================
<p align="center">
    <img src="./src/logo.png">
</p>

<h1 align="center">ChatGPT Box</h1>

<div align="center">

Integrasi Deep ChatGPT di browser Anda, sepenuhnya gratis.

[![license][license-image]][license-url]
[![release][release-image]][release-url]
[![size](https://img.shields.io/badge/minified%20size-390%20kB-blue)][release-url]
[![verfiy][verify-image]][verify-url]

[Inggris](README.md) &nbsp;&nbsp;|&nbsp;&nbsp; Indonesia &nbsp;&nbsp;|&nbsp;&nbsp; [简体中文](README_ZH.md) &nbsp;&nbsp;|&nbsp;&nbsp; [日本語](README_JA.md) &nbsp;&nbsp;|&nbsp;&nbsp; [Türkçe](README_TR.md)

### Install

[![Chrome][Chrome-image]][Chrome-url]
[![Edge][Edge-image]][Edge-url]
[![Firefox][Firefox-image]][Firefox-url]
[![Safari][Safari-image]][Safari-url]
[![Android][Android-image]][Android-url]
[![Github][Github-image]][Github-url]

[Panduan](https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Guide) &nbsp;&nbsp;|&nbsp;&nbsp; [Pratinjau](#Pratinjau) &nbsp;&nbsp;|&nbsp;&nbsp; [Pengembangan & Berkontribusi][dev-url] &nbsp;&nbsp;|&nbsp;&nbsp; [Demonstrasi Video](https://www.youtube.com/watch?v=E1smDxJvTRs) &nbsp;&nbsp;|&nbsp;&nbsp; [Kredit](#Kredit)

[dev-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Development&Contributing

[license-image]: http://img.shields.io/badge/license-MIT-blue.svg

[license-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/blob/master/LICENSE

[release-image]: https://img.shields.io/github/release/ChatGPTBox-dev/chatGPTBox.svg

[release-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/releases/latest

[verify-image]: https://github.com/ChatGPTBox-dev/chatGPTBox/workflows/verify-configs/badge.svg

[verify-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/actions/workflows/verify-configs.yml

[Chrome-image]: https://img.shields.io/badge/-Chrome-brightgreen?logo=google-chrome&logoColor=white

[Chrome-url]: https://chrome.google.com/webstore/detail/chatgptbox/eobbhoofkanlmddnplfhnmkfbnlhpbbo

[Edge-image]: https://img.shields.io/badge/-Edge-blue?logo=microsoft-edge&logoColor=white

[Edge-url]: https://microsoftedge.microsoft.com/addons/detail/fission-chatbox-best/enjmfilpkbbabhgeoadmdpjjpnahkogf

[Firefox-image]: https://img.shields.io/badge/-Firefox-orange?logo=firefox-browser&logoColor=white

[Firefox-url]: https://addons.mozilla.org/firefox/addon/chatgptbox/

[Safari-image]: https://img.shields.io/badge/-Safari-blue?logo=safari&logoColor=white

[Safari-url]: https://apps.apple.com/app/fission-chatbox/id6446611121

[Android-image]: https://img.shields.io/badge/-Android-brightgreen?logo=android&logoColor=white

[Android-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Install#install-to-android

[Github-image]: https://img.shields.io/badge/-Github-black?logo=github&logoColor=white

[Github-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Install

</div>

## Berita

- Ekstensi ini **tidak** mengumpulkan data Anda. Anda dapat memverifikasinya dengan melakukan pencarian global untuk `fetch(` dan `XMLHttpRequest(` dalam kode untuk menemukan semua panggilan permintaan jaringan. Jumlah kode tidak banyak, jadi mudah untuk melakukannya.

- Anda dapat menggunakan proyek seperti https://github.com/BerriAI/litellm / https://github.com/songquanpeng/one-api untuk mengkonversi API LLM ke dalam format OpenAI dan menggunakannya bersama dengan mode `Custom Model` dari ChatGPTBox

- Anda juga dapat menggunakan [Ollama](https://github.com/ChatGPTBox-dev/chatGPTBox/issues/616#issuecomment-1975186467) / https://openrouter.ai/docs#models dengan mode `Custom Model` dari ChatGPTBox

## ✨ Fitur

- 🌈 Panggil kotak dialog percakapan di halaman apa pun kapan saja. (<kbd>Ctrl</kbd>+<kbd>B</kbd>)
- 📱 Dukungan untuk perangkat seluler.
- 📓 Ringkaskan halaman apa pun dengan menu klik kanan. (<kbd>Alt</kbd>+<kbd>B</kbd>)
- 📖 Halaman percakapan independen. (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>H</kbd>)
- 🔗 Dukungan untuk beberapa API (Web API untuk pengguna Gratis dan Plus, GPT-3.5, GPT-4, Claude, New Bing, Moonshot, Self-Hosted, Azure, dll.).
- 📦 Integrasi untuk berbagai situs web yang umum digunakan (Reddit, Quora, YouTube, GitHub, GitLab, StackOverflow, Zhihu, Bilibili). (Terinspirasi dari [wimdenherder](https://github.com/wimdenherder))
- 🔍 Integrasi dengan semua mesin pencari utama, dan permintaan kustom untuk mendukung situs tambahan.
- 🧰 Alat pemilihan dan menu klik kanan untuk melakukan berbagai tugas, seperti terjemahan, ringkasan, penyempurnaan,
  analisis sentimen, pembagian paragraf, penjelasan kode, dan permintaan.
- 🗂️ Dukungan kartu statis untuk kotak percakapan bercabang.
- 🖨️ Mudah menyimpan catatan percakapan lengkap atau menyalinnya sebagian.
- 🎨 Dukungan rendering yang kuat, baik untuk penyorotan kode maupun rumus matematika kompleks.
- 🌍 Dukungan preferensi bahasa.
- 📝 Dukungan alamat API kustom.
- ⚙️ Semua adaptasi situs dan alat pemilihan (gelembung) dapat dinonaktifkan atau diaktifkan secara bebas, nonaktifkan modul yang tidak diperlukan.
- 💡 Alat pemilihan dan adaptasi situs mudah untuk dikembangkan dan diperluas, lihat bagian [Pengembangan & Berkontribusi][dev-url].
- 😉 Berbicara untuk meningkatkan kualitas jawaban.

## Pratinjau

<div align="center">

**Integrasi Mesin Pencari, Jendela Mengapung, Percakapan Cabang**

![preview_google_floatingwindow_conversationbranch](screenshots/preview_google_floatingwindow_conversationbranch.jpg)

**Integrasi dengan Situs Web yang Umum Digunakan, Alat Pemilihan**

![preview_reddit_selectiontools](screenshots/preview_reddit_selectiontools.jpg)

**Halaman Percakapan Independen**

![preview_independentpanel](screenshots/preview_independentpanel.jpg)

**Analisis Git, Menu Klik Kanan**

![preview_github_rightclickmenu](screenshots/preview_github_rightclickmenu.jpg)

**Ringkasan Video**

![preview_youtube](screenshots/preview_youtube.jpg)

**Dukungan Perangkat Seluler**

![image](https://user-images.githubusercontent.com/13366013/225529110-9221c8ce-ad41-423e-b6ec-097981e74b66.png)

**Pengaturan**

![preview_settings](screenshots/preview_settings.jpg)

</div>

## Kredit

Proyek ini didasarkan pada salah satu repositori saya yang lain, [josStorer/chatGPT-search-engine-extension](https://github.com/josStorer/chatGPT-search-engine-extension)

[josStorer/chatGPT-search-engine-extension](https://github.com/josStorer/chatGPT-search-engine-extension) bercabang
dari [wong2/chat-gpt-google-extension](https://github.com/wong2/chat-gpt-google-extension) (Saya belajar banyak dari situ)
dan terlepas sejak 14 Desember 2022

[wong2/chat-gpt-google-extension](https://github.com/wong2/chat-gpt-google-extension) terinspirasi
oleh [ZohaibAhmed/ChatGPT-Google](https://github.com/ZohaibAhmed/ChatGPT-Google) ([upstream-c54528b](https://github.com/wong2/chatgpt-google-extension/commit/c54528b0e13058ab78bfb433c92603db017d1b6b))


================================================
FILE: README_JA.md
================================================
<p align="center">
    <img src="./src/logo.png">
</p>

<h1 align="center">ChatGPT Box</h1>

<div align="center">

深い ChatGPT 統合をブラウザに、完全無料で。

[![license][license-image]][license-url]
[![release][release-image]][release-url]
[![size](https://img.shields.io/badge/minified%20size-390%20kB-blue)][release-url]
[![verfiy][verify-image]][verify-url]

[English](README.md) &nbsp;&nbsp;|&nbsp;&nbsp; [Indonesia](README_IN.md) &nbsp;&nbsp;|&nbsp;&nbsp; [简体中文](README_ZH.md) &nbsp;&nbsp;|&nbsp;&nbsp; 日本語 &nbsp;&nbsp;|&nbsp;&nbsp; [Türkçe](README_TR.md)

### インストール

[![Chrome][Chrome-image]][Chrome-url]
[![Edge][Edge-image]][Edge-url]
[![Firefox][Firefox-image]][Firefox-url]
[![Safari][Safari-image]][Safari-url]
[![Android][Android-image]][Android-url]
[![Github][Github-image]][Github-url]

[ガイド](https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Guide) &nbsp;&nbsp;|&nbsp;&nbsp; [プレビュー](#プレビュー) &nbsp;&nbsp;|&nbsp;&nbsp; [開発 & コントリビュート][dev-url] &nbsp;&nbsp;|&nbsp;&nbsp; [ビデオデモ](https://www.youtube.com/watch?v=E1smDxJvTRs) &nbsp;&nbsp;|&nbsp;&nbsp; [クレジット](#クレジット)

[dev-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Development&Contributing

[license-image]: http://img.shields.io/badge/license-MIT-blue.svg

[license-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/blob/master/LICENSE

[release-image]: https://img.shields.io/github/release/ChatGPTBox-dev/chatGPTBox.svg

[release-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/releases/latest

[verify-image]: https://github.com/ChatGPTBox-dev/chatGPTBox/workflows/verify-configs/badge.svg

[verify-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/actions/workflows/verify-configs.yml

[Chrome-image]: https://img.shields.io/badge/-Chrome-brightgreen?logo=google-chrome&logoColor=white

[Chrome-url]: https://chrome.google.com/webstore/detail/chatgptbox/eobbhoofkanlmddnplfhnmkfbnlhpbbo

[Edge-image]: https://img.shields.io/badge/-Edge-blue?logo=microsoft-edge&logoColor=white

[Edge-url]: https://microsoftedge.microsoft.com/addons/detail/fission-chatbox-best/enjmfilpkbbabhgeoadmdpjjpnahkogf

[Firefox-image]: https://img.shields.io/badge/-Firefox-orange?logo=firefox-browser&logoColor=white

[Firefox-url]: https://addons.mozilla.org/firefox/addon/chatgptbox/

[Safari-image]: https://img.shields.io/badge/-Safari-blue?logo=safari&logoColor=white

[Safari-url]: https://apps.apple.com/app/fission-chatbox/id6446611121

[Android-image]: https://img.shields.io/badge/-Android-brightgreen?logo=android&logoColor=white

[Android-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Install#install-to-android

[Github-image]: https://img.shields.io/badge/-Github-black?logo=github&logoColor=white

[Github-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Install

</div>

## ニュース

- この拡張機能はあなたのデータを収集しません。コード内の `fetch(` と `XMLHttpRequest(` をグローバル検索して、すべてのネットワークリクエストの呼び出しを見つけることで確認できます。コードの量はそれほど多くないので、簡単にできます。

- このツールは、あなたが明示的に要求しない限り、ChatGPT にデータを送信しません。デフォルトでは、拡張機能は手動で有効にする必要があります ChatGPT へのリクエストは、"Ask ChatGPT" をクリックするか、選択フローティングツールをトリガーした場合にのみ送信されます。(issue #407)

- https://github.com/BerriAI/litellm / https://github.com/songquanpeng/one-api のようなプロジェクトを使用して、LLM APIをOpenAI形式に変換し、それらをChatGPTBoxの `カスタムモデル` モードと組み合わせて使用することができます

- もちろんです。ChatGPTBoxの `カスタムモデル` モードを使用する際には、[Ollama](https://github.com/ChatGPTBox-dev/chatGPTBox/issues/616#issuecomment-1975186467) / https://openrouter.ai/docs#models もご利用いただけます

## ✨ 機能

- 🌈 いつでもどのページでもチャットダイアログボックスを呼び出すことができます。 (<kbd>Ctrl</kbd>+<kbd>B</kbd>)
- 📱 モバイル機器のサポート。
- 📓 右クリックメニューで任意のページを要約。 (<kbd>Alt</kbd>+<kbd>B</kbd>)
- 📖 独立した会話ページ。 (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>H</kbd>)
- 🔗 複数の API をサポート(無料および Plus ユーザー向け Web API、GPT-3.5、GPT-4、Claude、New Bing、Moonshot、セルフホスト、Azure など)。
- 📦 よく使われる様々なウェブサイト(Reddit、Quora、YouTube、GitHub、GitLab、StackOverflow、Zhihu、Bilibili)の統合。 ([wimdenherder](https://github.com/wimdenherder) にインスパイアされました)
- 🔍 すべての主要検索エンジンと統合し、追加のサイトをサポートするためのカスタムクエリ。
- 🧰 選択ツールと右クリックメニューで、翻訳、要約、推敲、感情分析、段落分割、コード説明、クエリーなど、さまざまなタスクを実行できます。
- 🗂️ 静的なカードは、複数の支店での会話のためのフローティングチャットボックスをサポートしています。
- 🖨️ チャット記録を完全に保存することも、部分的にコピーすることも簡単です。
- 🎨 コードのハイライトや複雑な数式など、強力なレンダリングをサポート。
- 🌍 言語設定のサポート。
- 📝 カスタム API アドレスのサポート
- ⚙️ すべてのサイト適応と選択ツール(バブル)は、自由にオンまたはオフに切り替えることができ、不要なモジュールを無効にすることができます。
- 💡 セレクションツールやサイトへの適応は簡単に開発・拡張できます。[開発 & コントリビュート][dev-url]のセクションを参照。
- 😉 チャットして回答の質を高められます。

## プレビュー

<div align="center">

**検索エンジンの統合、フローティングウィンドウ、会話ブランチ**

![preview_google_floatingwindow_conversationbranch](screenshots/preview_google_floatingwindow_conversationbranch.jpg)

**よく使われるウェブサイトや選択ツールとの統合**

![preview_reddit_selectiontools](screenshots/preview_reddit_selectiontools.jpg)

**独立会話ページ**

![preview_independentpanel](screenshots/preview_independentpanel.jpg)

**Git 分析、右クリックメニュー**

![preview_github_rightclickmenu](screenshots/preview_github_rightclickmenu.jpg)

**ビデオ要約**

![preview_youtube](screenshots/preview_youtube.jpg)

**モバイルサポート**

![image](https://user-images.githubusercontent.com/13366013/225529110-9221c8ce-ad41-423e-b6ec-097981e74b66.png)

**設定**

![preview_settings](screenshots/preview_settings.jpg)

</div>

## クレジット

このプロジェクトは、私の他のリポジトリ [josStorer/chatGPT-search-engine-extension](https://github.com/josStorer/chatGPT-search-engine-extension) に基づいています

[josStorer/chatGPT-search-engine-extension](https://github.com/josStorer/chatGPT-search-engine-extension) は [wong2/chat-gpt-google-extension](https://github.com/wong2/chat-gpt-google-extension) (参考にしました)からフォークされ、2022年12月14日から切り離されています

[wong2/chat-gpt-google-extension](https://github.com/wong2/chat-gpt-google-extension) は [ZohaibAhmed/ChatGPT-Google](https://github.com/ZohaibAhmed/ChatGPT-Google) にインスパイアされています([upstream-c54528b](https://github.com/wong2/chatgpt-google-extension/commit/c54528b0e13058ab78bfb433c92603db017d1b6b))


================================================
FILE: README_TR.md
================================================
<p align="center">
    <img src="./src/logo.png">
</p>

<h1 align="center">ChatGPT Box</h1>

<div align="center">

Tarayıcınıza derin ChatGPT entegrasyonu, tamamen ücretsiz.


[![license][license-image]][license-url]
[![release][release-image]][release-url]
[![size](https://img.shields.io/badge/minified%20size-390%20kB-blue)][release-url]
[![verfiy][verify-image]][verify-url]

[English](README.md) &nbsp;&nbsp;|&nbsp;&nbsp; [Indonesia](README_IN.md) &nbsp;&nbsp;|&nbsp;&nbsp; [简体中文](README_ZH.md) &nbsp;&nbsp;|&nbsp;&nbsp; [日本語](README_JA.md) &nbsp;&nbsp;|&nbsp;&nbsp; Türkçe

### Yükle

[![Chrome][Chrome-image]][Chrome-url]
[![Edge][Edge-image]][Edge-url]
[![Firefox][Firefox-image]][Firefox-url]
[![Safari][Safari-image]][Safari-url]
[![Android][Android-image]][Android-url]
[![Github][Github-image]][Github-url]

[Rehber](https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Guide) &nbsp;&nbsp;|&nbsp;&nbsp; [Önizleme](#Preview) &nbsp;&nbsp;|&nbsp;&nbsp; [Gelişim ve Katkı Sağlama][dev-url] &nbsp;&nbsp;|&nbsp;&nbsp; [Video](https://www.youtube.com/watch?v=E1smDxJvTRs) &nbsp;&nbsp;|&nbsp;&nbsp; [Credit](#Credit)

[dev-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Development&Contributing

[license-image]: http://img.shields.io/badge/license-MIT-blue.svg

[license-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/blob/master/LICENSE

[release-image]: https://img.shields.io/github/release/ChatGPTBox-dev/chatGPTBox.svg

[release-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/releases/latest

[verify-image]: https://github.com/ChatGPTBox-dev/chatGPTBox/workflows/verify-configs/badge.svg

[verify-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/actions/workflows/verify-configs.yml

[Chrome-image]: https://img.shields.io/badge/-Chrome-brightgreen?logo=google-chrome&logoColor=white

[Chrome-url]: https://chrome.google.com/webstore/detail/chatgptbox/eobbhoofkanlmddnplfhnmkfbnlhpbbo

[Edge-image]: https://img.shields.io/badge/-Edge-blue?logo=microsoft-edge&logoColor=white

[Edge-url]: https://microsoftedge.microsoft.com/addons/detail/fission-chatbox-best/enjmfilpkbbabhgeoadmdpjjpnahkogf

[Firefox-image]: https://img.shields.io/badge/-Firefox-orange?logo=firefox-browser&logoColor=white

[Firefox-url]: https://addons.mozilla.org/firefox/addon/chatgptbox/

[Safari-image]: https://img.shields.io/badge/-Safari-blue?logo=safari&logoColor=white

[Safari-url]: https://apps.apple.com/app/fission-chatbox/id6446611121

[Android-image]: https://img.shields.io/badge/-Android-brightgreen?logo=android&logoColor=white

[Android-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Install#install-to-android

[Github-image]: https://img.shields.io/badge/-Github-black?logo=github&logoColor=white

[Github-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Install

</div>

## Bilgilendirme

- Bu eklenti hiçbir verinizi **toplamaz**. Kod içinde network isteği çağrılarını bulmak için `fetch(` ve `XMLHttpRequest(` için global bir arama yaparak bunu doğrulayabilirsiniz. Kod miktarı fazla değil, bu yüzden yapılması kolaydır.

- Bu araç ChatGPT'ye siz açıkça belirtmediğiniz sürece hiçbir veri iletmez. Varsayılan olarak, eklentinin manuel olarak aktif hale getirilmesi gerekmektedir. Özellikle, sadece "ChatGPT'ye Sor" butonuna basarsanız ChatGPT'ye istek atar veya yüzen seçim araçlarını tetiklerseniz — Bu yalnızca GPT API modlarını kullandığınızda uygulanır (konu #407)

- Proje olarak https://github.com/BerriAI/litellm / https://github.com/songquanpeng/one-api gibi şeyleri kullanarak LLM API'larını OpenAI formatına dönüştürebilir ve bunları ChatGPTBox'ın `Custom Model` modu ile birlikte kullanabilirsiniz

- ChatGPTBox'un `Custom Model` modu ile [Ollama](https://github.com/ChatGPTBox-dev/chatGPTBox/issues/616#issuecomment-1975186467) / https://openrouter.ai/docs#models adresini de kullanabilirsiniz

## ✨ Özellikler

- 🌈 Sohbet diyalog kutusunu istediğiniz zaman çağırma. (<kbd>Ctrl</kbd>+<kbd>B</kbd>)
- 📱 Mobil cihaz desteği.
- 📓 Herhangi bir sayfayı sağ tık menüsüyle özetleme (<kbd>Alt</kbd>+<kbd>B</kbd>)
- 📖 Bağımsız konuşma sayfası. (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>H</kbd>)
- 🔗 Çoklu API desteği (Ücretsiz ve Plus kullanıcıları için Web API , GPT-3.5, GPT-4, Claude, New Bing, Moonshot, Self-Hosted, Azure vs.).
- 📦 Çeşitli olarak yaygın kullanılan websiteler için entegrasyon (Reddit, Quora, YouTube, GitHub, GitLab, StackOverflow, Zhihu, Bilibili). ([wimdenherder](https://github.com/wimdenherder)'den esinlenilmiştir)
- 🔍 Tüm popüler arama motorlarına entegrasyon ve ek siteleri desteklemek için özel sorgu desteği 
- 🧰 Çeşitli görevleri yerine getirmek için, seçim aracı ve sağ tık menüsü (Çeviri, Özetleme,Polishing, Duygu Analizi, Paragraf Bölme, Kod Açıklama ve Sorgular gibi.)
- 🗂️ Çok dallı konuşmalar için statik yüzen kart kutuları desteği.
- 🖨️ Kolaylıkla tam sohbet kayıtlarınızı kaydedin veya kısmi olarak kopyalayın.
- 🎨 Güçlü render'lama desteği, ister kod için olsun ister karışık matematik formülleri için.
- 🌍 Dil tercih desteği.
- 📝 Özel API adres desteği.
- ⚙️ Tüm site adaptasyonları ve seçim araçları(sohbet balonu) özgürce açıp kapatılabilir, ihtiyacınız olmayan modülleri kapatın.
- 💡 Seçim araçları ve site adaptasyonunun geliştirilmesi kolay ve geniştir, [Development&Contributing][dev-url] bölümüne bakınız.
- 😉 Yanıt kalitesini artırmak için sohbet edin.

## Önizleme

<div align="center">

**Arama Motoru Entegrasyonu, Yüzen Pencereler, Konuşma Dalları**

![preview_google_floatingwindow_conversationbranch](screenshots/preview_google_floatingwindow_conversationbranch.jpg)

**Yaygın Olarak Kullanılan Sitelerle Entegrasyon, Seçim Araçları**

![preview_reddit_selectiontools](screenshots/preview_reddit_selectiontools.jpg)

**Bağımsız Konuşma Sayfası**

![preview_independentpanel](screenshots/preview_independentpanel.jpg)

**Git Analizi, Sağ Tık Menüsü**

![preview_github_rightclickmenu](screenshots/preview_github_rightclickmenu.jpg)

**Video Özeti**

![preview_youtube](screenshots/preview_youtube.jpg)

**Mobil Desteği**

![image](https://user-images.githubusercontent.com/13366013/225529110-9221c8ce-ad41-423e-b6ec-097981e74b66.png)

**Ayarlar**

![preview_settings](screenshots/preview_settings.jpg)

</div>

## Katkıda Bulunanlar

Bu proje diğer repolarımın birisinden baz alınmıştır.
[josStorer/chatGPT-search-engine-extension](https://github.com/josStorer/chatGPT-search-engine-extension)

[josStorer/chatGPT-search-engine-extension](https://github.com/josStorer/chatGPT-search-engine-extension) projesi [wong2/chat-gpt-google-extension](https://github.com/wong2/chat-gpt-google-extension) projesinden "fork"lanmıştır (Ondan çok şey öğrendim)
ve 14 Aralık 2022'den beri bağımsızım

[wong2/chat-gpt-google-extension](https://github.com/wong2/chat-gpt-google-extension) projesi [ZohaibAhmed/ChatGPT-Google](https://github.com/ZohaibAhmed/ChatGPT-Google) ([upstream-c54528b](https://github.com/wong2/chatgpt-google-extension/commit/c54528b0e13058ab78bfb433c92603db017d1b6b)) projesinden esinlenilmiştir


================================================
FILE: README_ZH.md
================================================
<p align="center">
    <img src="./src/logo.png">
</p>

<h1 align="center">ChatGPT Box</h1>

<div align="center">

将ChatGPT深度集成到浏览器中, 你所需要的一切均在于此

[![license][license-image]][license-url]
[![release][release-image]][release-url]
[![size](https://img.shields.io/badge/minified%20size-390%20kB-blue)][release-url]
[![verfiy][verify-image]][verify-url]

[English](README.md) &nbsp;&nbsp;|&nbsp;&nbsp; [Indonesia](README_IN.md) &nbsp;&nbsp;|&nbsp;&nbsp; 简体中文 &nbsp;&nbsp;|&nbsp;&nbsp; [日本語](README_JA.md) &nbsp;&nbsp;|&nbsp;&nbsp; [Türkçe](README_TR.md)

### 安装链接

[![Chrome][Chrome-image]][Chrome-url]
[![Edge][Edge-image]][Edge-url]
[![Firefox][Firefox-image]][Firefox-url]
[![Safari][Safari-image]][Safari-url]
[![Android][Android-image]][Android-url]
[![Github][Github-image]][Github-url]

[使用指南](https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Guide) &nbsp;&nbsp;|&nbsp;&nbsp; [效果预览](#Preview) &nbsp;&nbsp;|&nbsp;&nbsp; [开发&贡献][dev-url] &nbsp;&nbsp;|&nbsp;&nbsp; [视频演示](https://www.bilibili.com/video/BV1524y1x7io) &nbsp;&nbsp;|&nbsp;&nbsp; [鸣谢](#Credit)

[dev-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Development&Contributing

[license-image]: http://img.shields.io/badge/license-MIT-blue.svg

[license-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/blob/master/LICENSE

[release-image]: https://img.shields.io/github/release/ChatGPTBox-dev/chatGPTBox.svg

[release-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/releases/latest

[verify-image]: https://github.com/ChatGPTBox-dev/chatGPTBox/workflows/verify-configs/badge.svg

[verify-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/actions/workflows/verify-configs.yml

[Chrome-image]: https://img.shields.io/badge/-Chrome-brightgreen?logo=google-chrome&logoColor=white

[Chrome-url]: https://chrome.google.com/webstore/detail/chatgptbox/eobbhoofkanlmddnplfhnmkfbnlhpbbo

[Edge-image]: https://img.shields.io/badge/-Edge-blue?logo=microsoft-edge&logoColor=white

[Edge-url]: https://microsoftedge.microsoft.com/addons/detail/fission-chatbox-best/enjmfilpkbbabhgeoadmdpjjpnahkogf

[Firefox-image]: https://img.shields.io/badge/-Firefox-orange?logo=firefox-browser&logoColor=white

[Firefox-url]: https://addons.mozilla.org/firefox/addon/chatgptbox/

[Safari-image]: https://img.shields.io/badge/-Safari-blue?logo=safari&logoColor=white

[Safari-url]: https://apps.apple.com/app/fission-chatbox/id6446611121

[Android-image]: https://img.shields.io/badge/-Android-brightgreen?logo=android&logoColor=white

[Android-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Install#install-to-android

[Github-image]: https://img.shields.io/badge/-Github-black?logo=github&logoColor=white

[Github-url]: https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Install

</div>

## 新闻

- 这个扩展程序不收集你的数据, 你可以通过对代码全局搜索 `fetch(` 和 `XMLHttpRequest(` 找到所有的网络请求调用. 代码量不多, 所以很容易验证.

- 你可以使用像 https://github.com/BerriAI/litellm / https://github.com/songquanpeng/one-api 这样的项目,将各种 大语言模型 API 转换为OpenAI格式,并与ChatGPTBox的`自定义模型`模式结合使用

- 对于国内用户, 有GPT, Midjourney, Netflix等账号需求的, 可以考虑此站点购买合租, 此链接购买的订单也会给我带来一定收益, 作为对本项目的支持: https://nf.video/yinhe/web?sharedId=84599

- 三方API服务兼容, 查看 https://api2d.com/r/193934 和 https://openrouter.ai/docs#models, 该服务并不是由我提供的, 但对于获取账号困难的用户可以考虑, 使用方法: [视频](https://www.bilibili.com/video/BV1bo4y1h7Hb/) [图文](https://github.com/ChatGPTBox-dev/chatGPTBox/issues/166#issuecomment-1504704489)

- 离线/自托管模型 现已支持, 在`自定义模型`模式下使用, 具体查看 [Ollama](https://github.com/ChatGPTBox-dev/chatGPTBox/issues/616#issuecomment-1975186467) / [RWKV-Runner](https://github.com/josStorer/RWKV-Runner), 你还可以部署wenda (https://github.com/wenda-LLM/wenda), 配合自定义模型模式使用, 从而调用各类本地模型, 参考 [#397](https://github.com/ChatGPTBox-dev/chatGPTBox/issues/397) 修改API URL

## ✨ Features

- 🌈 在任何页面随时呼出聊天对话框 (<kbd>Ctrl</kbd>+<kbd>B</kbd>)
- 📱 支持手机等移动设备
- 📓 通过右键菜单总结任意页面 (<kbd>Alt</kbd>+<kbd>B</kbd>)
- 📖 独立对话页面 (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>H</kbd>)
- 🔗 多种API支持 (免费用户和Plus用户可用Web API, 此外还有GPT-3.5, GPT-4, Claude, NewBing, Moonshot, 自托管支持, Azure等)
- 📦 对各种常用网站的集成适配 (Reddit, Quora, YouTube, GitHub, GitLab, StackOverflow, Zhihu, Bilibili) (受到[wimdenherder](https://github.com/wimdenherder)启发)
- 🔍 对所有主流搜索引擎的适配, 并支持自定义查询以支持额外的站点
- 🧰 框选工具与右键菜单, 执行各种你的需求, 如翻译, 总结, 润色, 情感分析, 段落划分, 代码解释, 问询
- 🗂️ 静态卡片支持浮出聊天框, 进行多分支对话
- 🖨️ 随意保存你的完整对话记录, 或进行局部复制
- 🎨 强大的渲染支持, 不论是代码高亮, 还是复杂数学公式
- 🌍 多语言偏好支持
- 📝 [自定义API地址](https://github.com/Ice-Hazymoon/openai-scf-proxy)支持
- ⚙️ 所有站点适配与工具均可自由开关, 随时停用你不需要的模块
- 💡 工具与站点适配开发易于扩展, 对于开发人员易于自定义, 请查看[开发&贡献][dev-url]部分
- 😉 此外, 如果回答有任何不足, 直接聊天解决!

## Preview

<div align="center">

**搜索引擎适配, 浮动窗口, 对话分支**

![preview_google_floatingwindow_conversationbranch](screenshots/preview_google_floatingwindow_conversationbranch.jpg)

**常用站点集成, 选择浮动工具**

![preview_reddit_selectiontools](screenshots/preview_reddit_selectiontools.jpg)

**独立对话页面**

![preview_independentpanel](screenshots/preview_independentpanel.jpg)

**Git分析, 右键菜单**

![preview_github_rightclickmenu](screenshots/preview_github_rightclickmenu.jpg)

**视频总结**

![preview_youtube](screenshots/preview_youtube.jpg)

**移动端效果**

![image](https://user-images.githubusercontent.com/13366013/225529110-9221c8ce-ad41-423e-b6ec-097981e74b66.png)

**设置界面**

![preview_settings](screenshots/preview_settings.jpg)

</div>

## Credit

该项目基于我的另一个项目 [josStorer/chatGPT-search-engine-extension](https://github.com/josStorer/chatGPT-search-engine-extension)

[josStorer/chatGPT-search-engine-extension](https://github.com/josStorer/chatGPT-search-engine-extension)
fork自 [wong2/chat-gpt-google-extension](https://github.com/wong2/chat-gpt-google-extension)(我从中学到很多)
并在2022年12月14日与上游分离

[wong2/chat-gpt-google-extension](https://github.com/wong2/chat-gpt-google-extension) 的想法源于
[ZohaibAhmed/ChatGPT-Google](https://github.com/ZohaibAhmed/ChatGPT-Google) ([upstream-c54528b](https://github.com/wong2/chatgpt-google-extension/commit/c54528b0e13058ab78bfb433c92603db017d1b6b))


================================================
FILE: badges/coverage.json
================================================
{
  "schemaVersion": 1,
  "label": "coverage",
  "message": "17.69%",
  "color": "red"
}


================================================
FILE: build.mjs
================================================
import archiver from 'archiver'
import fs from 'fs-extra'
import path from 'path'
import webpack from 'webpack'
import os from 'os'
import ProgressBarPlugin from 'progress-bar-webpack-plugin'
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
import { EsbuildPlugin } from 'esbuild-loader'
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'

const outdir = 'build'

const __dirname = path.resolve()
const isProduction = process.argv[2] !== '--development' // --production and --analyze are both production
const isAnalyzing = process.argv[2] === '--analyze'
// Env helpers
function getBooleanEnv(val, defaultValue) {
  if (val == null) return defaultValue
  const s = String(val).trim().toLowerCase()
  if (s === '' || s === '0' || s === 'false' || s === 'no' || s === 'off') {
    return false
  }
  if (s === '1' || s === 'true' || s === 'yes' || s === 'on') {
    return true
  }
  console.warn(`[build] Unknown boolean env value "${val}", defaulting to ${defaultValue}`)
  return defaultValue
}
// Default: parallel build ON unless explicitly disabled
const parallelBuild = getBooleanEnv(process.env.BUILD_PARALLEL, true)
const isWatchOnce = getBooleanEnv(process.env.BUILD_WATCH_ONCE, false)
// Cache compression control: default none; allow override via env
function parseCacheCompressionOption(envVal) {
  if (envVal == null) return false
  const v = String(envVal).trim().toLowerCase()
  if (v === '' || v === '0' || v === 'false' || v === 'none') return false
  if (v === 'gzip' || v === 'brotli') return v
  console.warn(`[build] Unknown BUILD_CACHE_COMPRESSION="${envVal}", defaulting to no compression`)
  return false
}
const cacheCompressionOption = parseCacheCompressionOption(process.env.BUILD_CACHE_COMPRESSION)
let cpuCount = 1
try {
  // os.cpus() returns an array in Node.js; guard with try/catch for portability
  cpuCount = Math.max(1, os.cpus().length || 1)
} catch {
  cpuCount = 1
}
function parseThreadWorkerCount(envValue, cpuCount) {
  const maxWorkers = Math.max(1, cpuCount)
  if (envValue !== undefined && envValue !== null) {
    const rawStr = String(envValue).trim()
    if (/^[1-9]\d*$/.test(rawStr)) {
      const raw = Number(rawStr)
      if (raw > cpuCount) {
        console.warn(
          `[build] BUILD_THREAD_WORKERS=${raw} exceeds CPU count (${cpuCount}); capping to ${cpuCount}`,
        )
      }
      return Math.min(raw, cpuCount)
    }
    console.warn(`[build] Invalid BUILD_THREAD_WORKERS="${envValue}", defaulting to ${maxWorkers}`)
  }
  return maxWorkers
}
const threadWorkers = parseThreadWorkerCount(process.env.BUILD_THREAD_WORKERS, cpuCount)
// Thread-loader pool timeout constants (allow override via env)
// Keep worker pool warm briefly to amortize repeated builds while still exiting quickly in CI
let PRODUCTION_POOL_TIMEOUT_MS = 2000
if (process.env.BUILD_POOL_TIMEOUT) {
  const n = parseInt(process.env.BUILD_POOL_TIMEOUT, 10)
  if (Number.isFinite(n) && n > 0) {
    PRODUCTION_POOL_TIMEOUT_MS = n
  } else {
    console.warn(
      `[build] Invalid BUILD_POOL_TIMEOUT="${process.env.BUILD_POOL_TIMEOUT}", keep default ${PRODUCTION_POOL_TIMEOUT_MS}ms`,
    )
  }
}
// Enable threads by default; allow disabling via BUILD_THREAD=0/false/no/off
const enableThread = getBooleanEnv(process.env.BUILD_THREAD, true)
// Allow opt-in symlink resolution for linked/workspace development when needed
const resolveSymlinks = getBooleanEnv(process.env.BUILD_RESOLVE_SYMLINKS, false)

// Cache and resolve Sass implementation once per process
let sassImplPromise
function resolveSassImplementation(mod) {
  if (mod && typeof mod.info === 'string') return mod
  if (mod?.default && typeof mod.default.info === 'string') return mod.default
  return mod
}

async function getSassImplementation() {
  if (!sassImplPromise) {
    sassImplPromise = (async () => {
      try {
        const mod = await import('sass-embedded')
        return resolveSassImplementation(mod)
      } catch (e1) {
        try {
          const mod = await import('sass')
          return resolveSassImplementation(mod)
        } catch (e2) {
          console.error('[build] Failed to load sass-embedded:', e1)
          console.error('[build] Failed to load sass:', e2)
          throw new Error("No Sass implementation available. Install 'sass-embedded' or 'sass'.")
        }
      }
    })()
  }
  return sassImplPromise
}

async function deleteOldDir() {
  await fs.rm(outdir, { recursive: true, force: true })
}

async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, sourceBuildDir, callback) {
  const shared = [
    'preact',
    'webextension-polyfill',
    '@primer/octicons-react',
    'react-bootstrap-icons',
    'countries-list',
    'i18next',
    'react-i18next',
    'react-tabs',
    './src/utils',
    './src/_locales/i18n-react',
  ]
  if (isWithoutKatex) shared.push('./src/components')

  const sassImpl = await getSassImplementation()

  const dirKey = path.basename(sourceBuildDir || outdir)
  const variantParts = [
    isWithoutKatex ? 'no-katex' : 'with-katex',
    isWithoutTiktoken ? 'no-tiktoken' : 'with-tiktoken',
    minimal ? 'minimal' : 'full',
    dirKey,
    isProduction ? 'prod' : 'dev',
  ]
  const variantId = variantParts.join('__')

  const compiler = webpack({
    entry: {
      'content-script': {
        import: './src/content-script/index.jsx',
        dependOn: 'shared',
      },
      background: {
        import: './src/background/index.mjs',
      },
      popup: {
        import: './src/popup/index.jsx',
        dependOn: 'shared',
      },
      IndependentPanel: {
        import: './src/pages/IndependentPanel/index.jsx',
        dependOn: 'shared',
      },
      shared: shared,
    },
    output: {
      filename: '[name].js',
      path: path.resolve(__dirname, sourceBuildDir || outdir),
    },
    mode: isProduction ? 'production' : 'development',
    devtool: isProduction ? false : 'cheap-module-source-map',
    cache: {
      type: 'filesystem',
      name: `webpack-${variantId}`,
      // Only include dimensions that affect module outputs to avoid
      // unnecessary cache invalidations across machines/CI runners
      version: JSON.stringify({ PROD: isProduction }),
      // default none; override via BUILD_CACHE_COMPRESSION=gzip|brotli
      compression: cacheCompressionOption,
      buildDependencies: {
        config: [
          path.resolve('build.mjs'),
          ...['package.json', 'package-lock.json']
            .map((p) => path.resolve(p))
            .filter((p) => fs.existsSync(p)),
        ],
      },
    },
    optimization: {
      minimizer: [
        // Use esbuild for JS minification (faster than Terser)
        new EsbuildPlugin({
          target: 'es2017',
          legalComments: 'none',
        }),
        // Use esbuild-based CSS minify via css-minimizer plugin
        new CssMinimizerPlugin({
          minify: CssMinimizerPlugin.esbuildMinify,
        }),
      ],
      concatenateModules: !isAnalyzing,
    },
    plugins: [
      minimal
        ? new webpack.ProvidePlugin({
            Buffer: ['buffer', 'Buffer'],
          })
        : new webpack.ProvidePlugin({
            process: 'process/browser.js',
            Buffer: ['buffer', 'Buffer'],
          }),
      new ProgressBarPlugin({
        format: '  build [:bar] :percent (:elapsed seconds)',
        clear: false,
      }),
      new MiniCssExtractPlugin({
        filename: '[name].css',
      }),
      new BundleAnalyzerPlugin({
        analyzerMode: isAnalyzing ? 'static' : 'disable',
      }),
      ...(isWithoutKatex
        ? [
            new webpack.NormalModuleReplacementPlugin(/markdown\.jsx/, (result) => {
              if (result.request) {
                result.request = result.request.replace(
                  'markdown.jsx',
                  'markdown-without-katex.jsx',
                )
              }
            }),
          ]
        : []),
    ],
    resolve: {
      extensions: ['.jsx', '.mjs', '.js'],
      // Disable symlink resolution for consistent behavior/perf; enable via BUILD_RESOLVE_SYMLINKS=1 when working with linked deps
      symlinks: resolveSymlinks,
      alias: {
        parse5: path.resolve(__dirname, 'node_modules/parse5'),
        ...(minimal
          ? { buffer: path.resolve(__dirname, 'node_modules/buffer') }
          : {
              util: path.resolve(__dirname, 'node_modules/util'),
              buffer: path.resolve(__dirname, 'node_modules/buffer'),
              stream: 'stream-browserify',
              crypto: 'crypto-browserify',
            }),
      },
    },
    module: {
      rules: [
        {
          test: /\.m?jsx?$/,
          exclude: /(node_modules)/,
          resolve: {
            fullySpecified: false,
          },
          use: [
            ...(enableThread
              ? [
                  {
                    loader: 'thread-loader',
                    options: {
                      workers: threadWorkers,
                      // Ensure one-off dev build exits quickly
                      poolTimeout: isProduction
                        ? PRODUCTION_POOL_TIMEOUT_MS
                        : isWatchOnce
                        ? 0
                        : Infinity,
                    },
                  },
                ]
              : []),
            {
              loader: 'babel-loader',
              options: {
                cacheDirectory: true,
                cacheCompression: false,
                presets: ['@babel/preset-env'],
                plugins: [
                  ['@babel/plugin-transform-runtime'],
                  [
                    '@babel/plugin-transform-react-jsx',
                    {
                      runtime: 'automatic',
                      importSource: 'preact',
                    },
                  ],
                ],
              },
            },
          ],
        },
        {
          test: /\.s[ac]ss$/,
          use: [
            isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
            {
              loader: 'css-loader',
              options: {
                importLoaders: 1,
              },
            },
            {
              loader: 'sass-loader',
              options: {
                implementation: sassImpl,
                sassOptions: {
                  quietDeps: true,
                },
              },
            },
          ],
        },
        {
          test: /\.less$/,
          use: [
            isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
            {
              loader: 'css-loader',
              options: {
                importLoaders: 1,
              },
            },
            {
              loader: 'less-loader',
            },
          ],
        },
        {
          test: /\.css$/,
          use: [
            isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
            {
              loader: 'css-loader',
            },
          ],
        },
        {
          test: /\.(woff|ttf)$/,
          type: 'asset/resource',
          generator: {
            emit: false,
          },
        },
        {
          test: /\.woff2$/,
          type: 'asset/inline',
        },
        {
          test: /\.(jpg|png|svg)$/,
          type: 'asset/inline',
        },
        {
          test: /\.(graphql|gql)$/,
          loader: 'graphql-tag/loader',
        },
        isWithoutTiktoken
          ? {
              test: /crop-text\.mjs$/,
              loader: 'string-replace-loader',
              options: {
                multiple: [
                  {
                    search: "import { encode } from '@nem035/gpt-3-encoder'",
                    replace: '',
                  },
                  {
                    search: 'encode(',
                    replace: 'String(',
                  },
                ],
              },
            }
          : {},
        minimal
          ? {
              test: /styles\.scss$/,
              loader: 'string-replace-loader',
              options: {
                multiple: [
                  {
                    search: "@import '../fonts/styles.css';",
                    replace: '',
                  },
                ],
              },
            }
          : {},
        minimal
          ? {
              test: /index\.mjs$/,
              loader: 'string-replace-loader',
              options: {
                multiple: [
                  {
                    search: 'import { generateAnswersWithChatGLMApi }',
                    replace: '//',
                  },
                  {
                    search: 'await generateAnswersWithChatGLMApi',
                    replace: '//',
                  },
                ],
              },
            }
          : {},
      ],
    },
  })
  if (isProduction) {
    // Ensure compiler is properly closed after production runs
    compiler.run((err, stats) => {
      const hasErrors = !!(err || stats?.hasErrors?.())
      let callbackFailed = false
      const finishClose = () =>
        compiler.close((closeErr) => {
          if (closeErr) {
            console.error('Error closing compiler:', closeErr)
            process.exitCode = 1
          }
          if (hasErrors || callbackFailed) {
            process.exitCode = 1
          }
        })
      try {
        const ret = callback(err, stats)
        if (ret && typeof ret.then === 'function') {
          ret.then(finishClose, () => {
            callbackFailed = true
            finishClose()
          })
        } else {
          finishClose()
        }
      } catch (callbackErr) {
        console.error('[build] Callback error:', callbackErr)
        callbackFailed = true
        finishClose()
      }
    })
  } else {
    const watching = compiler.watch({}, (err, stats) => {
      const hasErrors = !!(err || stats?.hasErrors?.())
      // Normalize callback return into a Promise to catch synchronous throws
      const ret = Promise.resolve().then(() => callback(err, stats))
      if (isWatchOnce) {
        const finalize = (callbackFailed = false) =>
          watching.close((closeErr) => {
            if (closeErr) console.error('Error closing watcher:', closeErr)
            // Exit explicitly to prevent hanging processes in CI
            // Use non-zero exit code when errors occurred, including callback failures
            const shouldFail = hasErrors || closeErr || callbackFailed
            process.exit(shouldFail ? 1 : 0)
          })
        ret.then(
          () => finalize(false),
          () => finalize(true),
        )
      }
    })
  }
}

async function zipFolder(dir) {
  const zipPath = `${dir}.zip`
  await fs.ensureDir(path.dirname(zipPath))
  await new Promise((resolve, reject) => {
    const output = fs.createWriteStream(zipPath)
    const archive = archiver('zip', { zlib: { level: 9 } })
    let settled = false
    const fail = (err) => {
      if (!settled) {
        settled = true
        reject(err)
      }
    }
    const done = () => {
      if (!settled) {
        settled = true
        resolve()
      }
    }
    output.once('error', fail)
    archive.once('error', fail)
    archive.on('warning', (err) => {
      // Log non-fatal archive warnings for diagnostics
      console.warn('[build][zip] warning:', err)
    })
    // Resolve on close to ensure FD is flushed and closed
    output.once('close', done)
    // Ensure close is emitted after finish on some fast runners
    output.once('finish', () => {
      try {
        if (typeof output.close === 'function') output.close()
      } catch (_) {
        // ignore
      }
    })
    archive.pipe(output)
    archive.directory(dir, false)
    archive.finalize()
  })
}

async function copyFiles(entryPoints, targetDir) {
  await fs.ensureDir(targetDir)
  await Promise.all(
    entryPoints.map(async (entryPoint) => {
      try {
        await fs.copy(entryPoint.src, `${targetDir}/${entryPoint.dst}`)
      } catch (e) {
        const isCss = typeof entryPoint.dst === 'string' && entryPoint.dst.endsWith('.css')
        if (e && e.code === 'ENOENT') {
          if (!isProduction && isCss) {
            console.log(
              `[build] Skipping missing CSS file: ${entryPoint.src} -> ${entryPoint.dst} (placeholder will be created)`,
            )
            return
          }
          console.error('Missing build artifact:', `${entryPoint.src} -> ${entryPoint.dst}`)
        } else {
          console.error('Copy failed:', `${entryPoint.src} -> ${entryPoint.dst}`, e)
        }
        throw e
      }
    }),
  )
}

// In development, create placeholder CSS and sourcemap files to avoid 404 noise
async function ensureDevCssPlaceholders(cssFiles) {
  if (isProduction || cssFiles.length === 0) return
  await Promise.all(
    cssFiles.map(async (cssPath) => {
      if (!(await fs.pathExists(cssPath))) {
        await fs.outputFile(cssPath, '/* dev placeholder */\n')
      }
      const mapPath = `${cssPath}.map`
      if (!(await fs.pathExists(mapPath))) {
        await fs.outputFile(mapPath, '{"version":3,"sources":[],"mappings":"","names":[]}')
      }
    }),
  )
}

async function finishOutput(outputDirSuffix, sourceBuildDir = outdir) {
  const commonFiles = [
    { src: 'src/logo.png', dst: 'logo.png' },
    { src: 'src/rules.json', dst: 'rules.json' },

    { src: `${sourceBuildDir}/shared.js`, dst: 'shared.js' },
    { src: `${sourceBuildDir}/content-script.css`, dst: 'content-script.css' }, // shared

    { src: `${sourceBuildDir}/content-script.js`, dst: 'content-script.js' },

    { src: `${sourceBuildDir}/background.js`, dst: 'background.js' },

    { src: `${sourceBuildDir}/popup.js`, dst: 'popup.js' },
    { src: `${sourceBuildDir}/popup.css`, dst: 'popup.css' },
    { src: 'src/popup/index.html', dst: 'popup.html' },

    { src: `${sourceBuildDir}/IndependentPanel.js`, dst: 'IndependentPanel.js' },
    { src: 'src/pages/IndependentPanel/index.html', dst: 'IndependentPanel.html' },
    // Dev-only: copy external source maps for CSP-safe debugging
    ...(isProduction
      ? []
      : [
          { src: `${sourceBuildDir}/shared.js.map`, dst: 'shared.js.map' },
          { src: `${sourceBuildDir}/content-script.js.map`, dst: 'content-script.js.map' },
          { src: `${sourceBuildDir}/background.js.map`, dst: 'background.js.map' },
          { src: `${sourceBuildDir}/popup.js.map`, dst: 'popup.js.map' },
          { src: `${sourceBuildDir}/IndependentPanel.js.map`, dst: 'IndependentPanel.js.map' },
        ]),
  ]

  // chromium
  const chromiumOutputDir = `./${outdir}/chromium${outputDirSuffix}`
  await copyFiles(
    [...commonFiles, { src: 'src/manifest.json', dst: 'manifest.json' }],
    chromiumOutputDir,
  )
  await ensureDevCssPlaceholders(
    Array.from(
      new Set(
        commonFiles
          .filter((file) => file.dst.endsWith('.css'))
          .map((file) => path.join(chromiumOutputDir, file.dst)),
      ),
    ),
  )
  if (isProduction) await zipFolder(chromiumOutputDir)

  // firefox
  const firefoxOutputDir = `./${outdir}/firefox${outputDirSuffix}`
  await copyFiles(
    [...commonFiles, { src: 'src/manifest.v2.json', dst: 'manifest.json' }],
    firefoxOutputDir,
  )
  await ensureDevCssPlaceholders(
    Array.from(
      new Set(
        commonFiles
          .filter((file) => file.dst.endsWith('.css'))
          .map((file) => path.join(firefoxOutputDir, file.dst)),
      ),
    ),
  )
  if (isProduction) await zipFolder(firefoxOutputDir)
}

async function build() {
  await deleteOldDir()
  function createWebpackBuildPromise(isWithoutKatex, isWithoutTiktoken, minimal, tmpDir, suffix) {
    return new Promise((resolve, reject) => {
      const ret = runWebpack(
        isWithoutKatex,
        isWithoutTiktoken,
        minimal,
        tmpDir,
        async (err, stats) => {
          if (err || stats?.hasErrors?.()) {
            console.error(err || stats.toString())
            reject(err || new Error('webpack error'))
            return
          }
          try {
            await finishOutput(suffix, tmpDir)
            resolve()
          } catch (copyErr) {
            reject(copyErr)
          }
        },
      )
      // runWebpack is async; catch early rejections (e.g., failed dynamic imports)
      if (ret && typeof ret.then === 'function') ret.catch(reject)
    })
  }
  if (isProduction && !isAnalyzing) {
    const tmpFull = `${outdir}/.tmp-full`
    const tmpMin = `${outdir}/.tmp-min`
    try {
      if (parallelBuild) {
        const results = await Promise.allSettled([
          createWebpackBuildPromise(true, true, true, tmpMin, '-without-katex-and-tiktoken'),
          createWebpackBuildPromise(false, false, false, tmpFull, ''),
        ])
        const failed = results.find((result) => result.status === 'rejected')
        if (failed) {
          throw failed.reason
        }
      } else {
        await createWebpackBuildPromise(true, true, true, tmpMin, '-without-katex-and-tiktoken')
        await createWebpackBuildPromise(false, false, false, tmpFull, '')
      }
    } finally {
      await fs.rm(tmpFull, { recursive: true, force: true })
      await fs.rm(tmpMin, { recursive: true, force: true })
    }
    return
  }

  await new Promise((resolve, reject) => {
    const ret = runWebpack(false, false, false, outdir, async (err, stats) => {
      const hasErrors = !!(err || stats?.hasErrors?.())
      if (hasErrors) {
        console.error(err || stats.toString())
        // In normal dev watch, keep process alive on initial errors; only fail when watch-once
        if (isWatchOnce) {
          reject(err || new Error('webpack error'))
        }
        return
      }
      try {
        await finishOutput('')
        resolve()
      } catch (e) {
        // Packaging failure should stop even in dev to avoid silent success
        reject(e)
        if (isWatchOnce) {
          // Re-throw to surface an error and exit non-zero even if rejection isn't awaited
          throw e
        }
      }
    })
    // Early setup failures (e.g., dynamic imports) should fail fast
    if (ret && typeof ret.then === 'function') ret.catch(reject)
  })
}

build().catch((e) => {
  console.error(e)
  process.exit(1)
})


================================================
FILE: package.json
================================================
{
  "name": "chatgptbox",
  "engines": {
    "node": ">=22"
  },
  "scripts": {
    "build": "node build.mjs --production",
    "build:safari": "bash ./safari/build.sh",
    "dev": "node build.mjs --development",
    "analyze": "node build.mjs --analyze",
    "lint": "eslint --ext .js,.mjs,.jsx .",
    "test": "node --import ./tests/setup/browser-shim.mjs --test",
    "test:coverage": "c8 --all --reporter=text --reporter=lcov --reporter=json-summary --include=\"src/**/*.{mjs,jsx,js}\" node --import ./tests/setup/browser-shim.mjs --test",
    "lint:fix": "eslint --ext .js,.mjs,.jsx . --fix",
    "pretty": "prettier --write ./**/*.{js,mjs,jsx,json,css,scss}",
    "stage": "run-script-os",
    "stage:default": "git add $(git diff --name-only --cached --diff-filter=d)",
    "stage:win32": "powershell git add $(git diff --name-only --cached --diff-filter=d)",
    "verify": "node .github/workflows/scripts/verify-search-engine-configs.mjs"
  },
  "pre-commit": [
    "pretty",
    "stage",
    "lint"
  ],
  "dependencies": {
    "@babel/runtime": "^7.24.7",
    "@mozilla/readability": "^0.6.0",
    "@nem035/gpt-3-encoder": "^1.1.7",
    "@picocss/pico": "^1.5.13",
    "@primer/octicons-react": "^18.3.0",
    "buffer": "^6.0.3",
    "countries-list": "^2.6.1",
    "crypto-browserify": "^3.12.0",
    "diff": "^5.2.0",
    "file-saver": "^2.0.5",
    "github-markdown-css": "^5.6.1",
    "gpt-3-encoder": "^1.1.4",
    "graphql": "^16.9.0",
    "i18next": "^22.4.15",
    "js-sha3": "^0.9.3",
    "jsonwebtoken": "9.0.2",
    "katex": "^0.16.11",
    "lodash-es": "^4.17.21",
    "md5": "^2.3.0",
    "parse5": "^6.0.1",
    "preact": "^10.22.1",
    "process": "^0.11.10",
    "prop-types": "^15.8.1",
    "random-int": "^3.0.0",
    "react": "npm:@preact/compat@^17.1.2",
    "react-bootstrap-icons": "^1.11.4",
    "react-dom": "npm:@preact/compat@^17.1.2",
    "react-draggable": "^4.4.6",
    "react-i18next": "^12.2.0",
    "react-markdown": "^8.0.7",
    "react-tabs": "^4.3.0",
    "react-toastify": "^9.1.3",
    "rehype-highlight": "^6.0.0",
    "rehype-katex": "^6.0.3",
    "rehype-raw": "^6.1.1",
    "remark-breaks": "^3.0.3",
    "remark-gfm": "^3.0.1",
    "remark-math": "^5.1.1",
    "stream-browserify": "^3.0.0",
    "util": "^0.12.5",
    "uuid": "^9.0.1",
    "webextension-polyfill": "^0.12.0"
  },
  "devDependencies": {
    "@babel/core": "^7.24.7",
    "@babel/plugin-transform-react-jsx": "^7.24.7",
    "@babel/plugin-transform-runtime": "^7.24.7",
    "@babel/preset-env": "^7.24.7",
    "@types/archiver": "^5.3.4",
    "@types/fs-extra": "^11.0.4",
    "@types/jsdom": "^21.1.7",
    "@types/webextension-polyfill": "^0.10.7",
    "archiver": "^5.3.2",
    "babel-loader": "^9.1.3",
    "c8": "^11.0.0",
    "css-loader": "^6.11.0",
    "css-minimizer-webpack-plugin": "^8.0.0",
    "esbuild": "^0.25.9",
    "esbuild-loader": "^4.3.0",
    "eslint": "^8.57.1",
    "eslint-plugin-react": "^7.34.3",
    "fs-extra": "^11.2.0",
    "graphql-tag": "^2.12.6",
    "jsdom": "^28.1.0",
    "less-loader": "^11.1.4",
    "mini-css-extract-plugin": "^2.9.0",
    "node-fetch": "^3.3.2",
    "pre-commit": "^1.2.2",
    "prettier": "^2.8.8",
    "progress-bar-webpack-plugin": "^2.1.0",
    "run-script-os": "^1.1.6",
    "sass": "^1.91.0",
    "sass-embedded": "^1.91.0",
    "sass-loader": "^16.0.5",
    "string-replace-loader": "^3.1.0",
    "style-loader": "^4.0.0",
    "thread-loader": "^4.0.4",
    "webpack": "^5.92.1",
    "webpack-bundle-analyzer": "^4.10.2"
  }
}


================================================
FILE: safari/appdmg.json
================================================
{
  "title": "Fission - ChatBox",
  "icon": "../src/logo.png",
  "contents": [
    { "x": 448, "y": 344, "type": "link", "path": "/Applications" },
    { "x": 192, "y": 344, "type": "file", "path": "../build/Fission - ChatBox.app" }
  ]
}


================================================
FILE: safari/build.sh
================================================
git apply safari/project.pre.patch
npm run build
xcrun safari-web-extension-converter ./build/firefox \
 --project-location ./build/safari --app-name "Fission - ChatBox" \
 --bundle-identifier dev.josStorer.chatGPTBox --force --no-prompt --no-open
git apply safari/project.patch
xcodebuild archive -project "./build/safari/Fission - ChatBox/Fission - ChatBox.xcodeproj" \
 -scheme "Fission - ChatBox (macOS)" -configuration Release -archivePath "./build/safari/Fission - ChatBox.xcarchive"
xcodebuild -exportArchive -archivePath "./build/safari/Fission - ChatBox.xcarchive" \
 -exportOptionsPlist ./safari/export-options.plist -exportPath ./build
npm install -D appdmg
rm ./build/safari.dmg
appdmg ./safari/appdmg.json ./build/safari.dmg

================================================
FILE: safari/export-options.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>method</key>
	<string>mac-application</string>
</dict>
</plist>

================================================
FILE: safari/project.patch
================================================
--- a/build/safari/Fission - ChatBox/Fission - ChatBox.xcodeproj/project.pbxproj
+++ b/build/safari/Fission - ChatBox/Fission - ChatBox.xcodeproj/project.pbxproj


================================================
FILE: safari/project.pre.patch
================================================
--- a/src/manifest.v2.json
+++ b/src/manifest.v2.json
@@ -1,5 +1,5 @@
 {
-  "name": "ChatGPTBox",
+  "name": "Fission - ChatBox",
   "description": "Integrating ChatGPT into your browser deeply, everything you need is here",
   "version": "0.0.0",
   "manifest_version": 2,
@@ -28,7 +28,7 @@
     "scripts": [
       "background.js"
     ],
-    "persistent": true
+    "persistent": true
   },
   "browser_action": {
     "default_popup": "popup.html?popup=true"


================================================
FILE: safari/project_developer.patch
================================================
--- a/build/safari/Fission - ChatBox/Fission - ChatBox.xcodeproj/project.pbxproj
+++ b/build/safari/Fission - ChatBox/Fission - ChatBox.xcodeproj/project.pbxproj
@@ -675,6 +675,7 @@
 			buildSettings = {
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = SMGV55KD3K;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = "iOS (Extension)/Info.plist";
 				INFOPLIST_KEY_CFBundleDisplayName = "Fission - ChatBox Extension";
@@ -690,7 +691,7 @@
 					"-framework",
 					SafariServices,
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.Fission---ChatBox.Extension";
+				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.chatGPTBox.Extension";
 				PRODUCT_NAME = "Fission - ChatBox Extension";
 				SDKROOT = iphoneos;
 				SKIP_INSTALL = YES;
@@ -705,6 +706,7 @@
 			buildSettings = {
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = SMGV55KD3K;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = "iOS (Extension)/Info.plist";
 				INFOPLIST_KEY_CFBundleDisplayName = "Fission - ChatBox Extension";
@@ -720,7 +722,7 @@
 					"-framework",
 					SafariServices,
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.Fission---ChatBox.Extension";
+				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.chatGPTBox.Extension";
 				PRODUCT_NAME = "Fission - ChatBox Extension";
 				SDKROOT = iphoneos;
 				SKIP_INSTALL = YES;
@@ -738,10 +740,12 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
+				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = SMGV55KD3K;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = "iOS (App)/Info.plist";
 				INFOPLIST_KEY_CFBundleDisplayName = "Fission - ChatBox";
+				INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
 				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
 				INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
 				INFOPLIST_KEY_UIMainStoryboardFile = Main;
@@ -752,14 +756,14 @@
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				MARKETING_VERSION = 1.0;
+				MARKETING_VERSION = 0.0.0;
 				OTHER_LDFLAGS = (
 					"-framework",
 					SafariServices,
 					"-framework",
 					WebKit,
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.Fission---ChatBox";
+				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.chatGPTBox";
 				PRODUCT_NAME = "Fission - ChatBox";
 				SDKROOT = iphoneos;
 				SWIFT_EMIT_LOC_STRINGS = YES;
@@ -775,10 +779,12 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
+				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = SMGV55KD3K;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = "iOS (App)/Info.plist";
 				INFOPLIST_KEY_CFBundleDisplayName = "Fission - ChatBox";
+				INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
 				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
 				INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
 				INFOPLIST_KEY_UIMainStoryboardFile = Main;
@@ -789,14 +795,14 @@
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				MARKETING_VERSION = 1.0;
+				MARKETING_VERSION = 0.0.0;
 				OTHER_LDFLAGS = (
 					"-framework",
 					SafariServices,
 					"-framework",
 					WebKit,
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.Fission---ChatBox";
+				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.chatGPTBox";
 				PRODUCT_NAME = "Fission - ChatBox";
 				SDKROOT = iphoneos;
 				SWIFT_EMIT_LOC_STRINGS = YES;
@@ -812,6 +818,7 @@
 				CODE_SIGN_ENTITLEMENTS = "macOS (Extension)/Fission - ChatBox.entitlements";
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = SMGV55KD3K;
 				ENABLE_HARDENED_RUNTIME = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = "macOS (Extension)/Info.plist";
@@ -828,7 +835,7 @@
 					"-framework",
 					SafariServices,
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.Fission---ChatBox.Extension";
+				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.chatGPTBox.Extension";
 				PRODUCT_NAME = "Fission - ChatBox Extension";
 				SDKROOT = macosx;
 				SKIP_INSTALL = YES;
@@ -843,6 +850,7 @@
 				CODE_SIGN_ENTITLEMENTS = "macOS (Extension)/Fission - ChatBox.entitlements";
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = SMGV55KD3K;
 				ENABLE_HARDENED_RUNTIME = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = "macOS (Extension)/Info.plist";
@@ -859,7 +867,7 @@
 					"-framework",
 					SafariServices,
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.Fission---ChatBox.Extension";
+				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.chatGPTBox.Extension";
 				PRODUCT_NAME = "Fission - ChatBox Extension";
 				SDKROOT = macosx;
 				SKIP_INSTALL = YES;
@@ -876,11 +884,13 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CODE_SIGN_ENTITLEMENTS = "macOS (App)/Fission - ChatBox.entitlements";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
+				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = SMGV55KD3K;
 				ENABLE_HARDENED_RUNTIME = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = "macOS (App)/Info.plist";
 				INFOPLIST_KEY_CFBundleDisplayName = "Fission - ChatBox";
+				INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
 				INFOPLIST_KEY_NSMainStoryboardFile = Main;
 				INFOPLIST_KEY_NSPrincipalClass = NSApplication;
 				LD_RUNPATH_SEARCH_PATHS = (
@@ -888,14 +898,14 @@
 					"@executable_path/../Frameworks",
 				);
 				MACOSX_DEPLOYMENT_TARGET = 10.14;
-				MARKETING_VERSION = 1.0;
+				MARKETING_VERSION = 0.0.0;
 				OTHER_LDFLAGS = (
 					"-framework",
 					SafariServices,
 					"-framework",
 					WebKit,
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.Fission---ChatBox";
+				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.chatGPTBox";
 				PRODUCT_NAME = "Fission - ChatBox";
 				SDKROOT = macosx;
 				SWIFT_EMIT_LOC_STRINGS = YES;
@@ -911,11 +921,13 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CODE_SIGN_ENTITLEMENTS = "macOS (App)/Fission - ChatBox.entitlements";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
+				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = SMGV55KD3K;
 				ENABLE_HARDENED_RUNTIME = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = "macOS (App)/Info.plist";
 				INFOPLIST_KEY_CFBundleDisplayName = "Fission - ChatBox";
+				INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
 				INFOPLIST_KEY_NSMainStoryboardFile = Main;
 				INFOPLIST_KEY_NSPrincipalClass = NSApplication;
 				LD_RUNPATH_SEARCH_PATHS = (
@@ -923,14 +935,14 @@
 					"@executable_path/../Frameworks",
 				);
 				MACOSX_DEPLOYMENT_TARGET = 10.14;
-				MARKETING_VERSION = 1.0;
+				MARKETING_VERSION = 0.0.0;
 				OTHER_LDFLAGS = (
 					"-framework",
 					SafariServices,
 					"-framework",
 					WebKit,
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.Fission---ChatBox";
+				PRODUCT_BUNDLE_IDENTIFIER = "dev.josStorer.chatGPTBox";
 				PRODUCT_NAME = "Fission - ChatBox";
 				SDKROOT = macosx;
 				SWIFT_EMIT_LOC_STRINGS = YES;


================================================
FILE: src/_locales/de/main.json
================================================
{
  "General": "Allgemein",
  "Selection Tools": "Auswahlwerkzeuge",
  "Sites": "Webseiten",
  "Advanced": "Erweiterte Einstellungen",
  "Donate": "Spenden",
  "Triggers": "Auslöser",
  "Theme": "Thema",
  "API Mode": "API-Modus",
  "Get": "Erhalten",
  "Preferred Language": "Bevorzugte Sprache",
  "Insert ChatGPT at the top of search results": "ChatGPT am Anfang der Suchergebnisse einfügen",
  "Lock scrollbar while answering": "Bildlaufleiste beim Beantworten sperren",
  "Current Version": "Aktuelle Version",
  "Latest": "Neueste Version",
  "Help | Changelog ": "Hilfe | Änderungsprotokoll",
  "Custom ChatGPT Web API Url": "Benutzerdefinierte ChatGPT-Web-API-URL",
  "Custom ChatGPT Web API Path": "Benutzerdefinierter ChatGPT-Web-API-Pfad",
  "Custom OpenAI API Url": "Benutzerdefinierte OpenAI-API-URL",
  "Custom Site Regex": "Benutzerdefinierter Website-Regex",
  "Exclusively use Custom Site Regex for website matching, ignoring built-in rules": "Nur benutzerdefinierten Website-Regex verwenden, um Website-Übereinstimmungen zu finden und interne Regeln ignorieren",
  "Input Query": "Eingabeaufforderung",
  "Append Query": "Am Ende anhängen",
  "Prepend Query": "Am Anfang hinzufügen",
  "Wechat Pay": "WeChat-Pay",
  "Type your question here\nEnter to send, shift + enter to break line": "Geben Sie Ihre Frage hier ein\nEnter zum Senden, Shift + Enter zum Zeilenumbruch",
  "Type your question here\nEnter to stop generating\nShift + enter to break line": "Geben Sie Ihre Frage hier ein\nEnter zum Stoppen der Generierung\nShift + Enter zum Zeilenumbruch",
  "Ask ChatGPT": "ChatGPT fragen",
  "No Input Found": "Keine Eingabe gefunden",
  "You": "Du",
  "Collapse": "Verkleinern",
  "Expand": "Erweitern",
  "Stop": "Stoppen",
  "Continue on official website": "Weiter auf der offiziellen Website",
  "Error": "Fehler",
  "Copy": "Kopieren",
  "Question": "Frage",
  "Answer": "Antwort",
  "Waiting for response...": "Warte auf Antwort...",
  "Close the Window": "Fenster schließen",
  "Pin the Window": "Fenster anheften",
  "Float the Window": "Fenster aufteilen",
  "Save Conversation": "Konversation speichern",
  "UNAUTHORIZED": "Unbefugt",
  "Please login at https://chatgpt.com first": "Bitte zuerst bei https://chatgpt.com anmelden",
  "Please login at https://claude.ai first, and then click the retry button": "Bitte zuerst bei https://claude.ai anmelden und dann auf die Schaltfläche Wiederholen klicken",
  "Please login at https://bing.com first": "Bitte zuerst bei https://bing.com anmelden",
  "Then open https://chatgpt.com/api/auth/session": "Dann öffne https://chatgpt.com/api/auth/session",
  "And refresh this page or type you question again": "Klicken Sie anschließend auf die Schaltfläche Wiederholen in der oberen rechten Ecke",
  "Consider creating an api key at https://platform.openai.com/account/api-keys": "Erwägen Sie ein API-Schlüssel unter https://platform.openai.com/account/api-keys zu erstellen",
  "OpenAI Security Check Required": "OpenAI-Sicherheitscheck erforderlich",
  "Please open https://chatgpt.com/api/auth/session": "Bitte öffne https://chatgpt.com/api/auth/session",
  "Please open https://chatgpt.com": "Bitte öffne https://chatgpt.com",
  "New Chat": "Neuer Chat",
  "Summarize Page": "Seite zusammenfassen",
  "Translate": "Übersetzen",
  "Translate (Bidirectional)": "Übersetzen (Bidirektional)",
  "Translate (To English)": "Übersetzen (Ins Englische)",
  "Translate (To Chinese)": "Übersetzen (Ins Chinesische)",
  "Summary": "Zusammenfassung",
  "Polish": "Polieren",
  "Sentiment Analysis": "Stimmungsanalyse",
  "Divide Paragraphs": "Abschnitte teilen",
  "Code Explain": "Code erklären",
  "Ask": "Fragen",
  "Always": "Immer",
  "Manually": "Manuell",
  "When query ends with question mark (?)": "Wenn die Abfrage mit einem Fragezeichen (?) endet",
  "Light": "Hell",
  "Dark": "Dunkel",
  "Auto": "Automatisch",
  "ChatGPT (Web)": "ChatGPT (Web)",
  "ChatGPT (Web, GPT-4)": "ChatGPT (Web, GPT-4)",
  "Bing (Web, GPT-4)": "Bing (Web, GPT-4)",
  "ChatGPT (GPT-3.5-turbo)": "ChatGPT (GPT-3.5-Turbo)",
  "OpenAI (GPT-3.5-turbo)": "OpenAI (GPT-3.5-Turbo)",
  "ChatGPT (GPT-4-8k)": "ChatGPT (GPT-4-8k)",
  "OpenAI (GPT-4-8k)": "OpenAI (GPT-4-8k)",
  "ChatGPT (GPT-4-32k)": "ChatGPT (GPT-4-32k)",
  "GPT-3.5": "GPT-3.5",
  "Custom Model": "Benutzerdefiniertes Modell",
  "Balanced": "Ausgeglichen",
  "Creative": "Kreativ",
  "Precise": "Präzise",
  "Fast": "Schnell",
  "API Key": "API-Schlüssel",
  "Model Name": "Modellname",
  "Custom Model API Url": "Benutzerdefinierte Modell-API-URL",
  "Loading...": "Laden...",
  "Feedback": "Feedback",
  "Confirm": "Bestätigen",
  "Clear Conversation": "Konversation löschen",
  "Retry": "Erneut versuchen",
  "Exceeded maximum context length": "Maximale Kontextlänge überschritten, bitte Konversation löschen und erneut versuchen",
  "Regenerate the answer after switching model": "Antwort nach dem Wechseln des Modells neu generieren",
  "Pin": "Anheften",
  "Unpin": "Loslösen",
  "Delete Conversation": "Konversation löschen",
  "Clear conversations": "Konversationen löschen",
  "Settings": "Einstellungen",
  "Feature Pages": "Funktionsseiten",
  "Keyboard Shortcuts": "Tastenkombinationen",
  "Open Conversation Page": "Konversationsseite öffnen",
  "Open Conversation Window": "Konversationsfenster öffnen",
  "Store to Independent Conversation Page": "Auf unabhängiger Konversationsseite speichern",
  "Keep Conversation Window in Background": "Chatfenster im Hintergrund halten, um es mit Tastenkombinationen in jeder Anwendung aufzurufen",
  "Max Response Token Length": "Maximale Tokenlänge der Antwort",
  "Max Conversation Length": "Maximale Gesprächslänge",
  "Always pin the floating window": "Immer das schwebende Fenster anheften",
  "Export": "Exportieren",
  "Always Create New Conversation Window": "Immer ein neues Chatfenster erstellen",
  "Please keep this tab open. You can now use the web mode of ChatGPTBox": "Bitte halten Sie diesen Tab geöffnet. Sie können jetzt den Webmodus von ChatGPTBox verwenden",
  "Go Back": "Zurück",
  "Pin Tab": "Tab anheften",
  "Modules": "Module",
  "API Params": "API-Parameter",
  "API Url": "API-URL",
  "Others": "Andere",
  "API Modes": "API-Modi",
  "Disable web mode history for better privacy protection, but it will result in unavailable conversations after a period of time": "Deaktivieren Sie die Verlaufsfunktion im Webmodus für besseren Datenschutz. Beachten Sie jedoch, dass die Gespräche nach einer gewissen Zeit nicht mehr verfügbar sind",
  "Display selection tools next to input box to avoid blocking": "Zeigen Sie Auswahlwerkzeuge neben dem Eingabefeld an, um die Sicht nicht zu blockieren",
  "Close All Chats In This Page": "Alle Chats auf dieser Seite schließen",
  "When Icon Clicked": "Beim Klicken auf das Symbol",
  "Open Settings": "Einstellungen öffnen",
  "Focus to input box after answering": "Nach der Antwort den Fokus auf das Eingabefeld legen",
  "Bing CaptchaChallenge": "Bing Captcha-Herausforderung: Sie müssen eine Überprüfung von Bing bestehen. Öffnen Sie https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx und senden Sie eine Nachricht.",
  "Exceeded quota": "Überschrittenes Kontingent: Prüfen Sie Ihr Guthaben oder Ablaufdatum unter folgendem Link: https://platform.openai.com/account/usage",
  "Rate limit": "Rate-Limit erreicht",
  "Jump to bottom": "Zum Ende springen",
  "Explain": "Erklären",
  "Failed to get arkose token.": "Arkose-Token konnte nicht abgerufen werden.",
  "Please keep https://chatgpt.com open and try again. If it still doesn't work, type some characters in the input box of chatgpt web page and try again.": "Bitte halten Sie https://chatgpt.com geöffnet und versuchen Sie es erneut. Wenn es immer noch nicht funktioniert, geben Sie einige Zeichen in das Eingabefeld der ChatGPT-Webseite ein und versuchen Sie es erneut.",
  "Open Side Panel": "Seitenleiste öffnen",
  "Generating...": "Generieren...",
  "moonshot token required, please login at https://kimi.com first, and then click the retry button": "Moonshot-Token erforderlich, bitte zuerst bei https://kimi.com anmelden und dann auf die Schaltfläche Wiederholen klicken",
  "Hide context menu of this extension": "Kontextmenü dieser Erweiterung ausblenden",
  "Custom Anthropic API Url": "Benutzerdefinierte Anthropic-API-URL",
  "Anthropic API Key": "Anthropic-API-Schlüssel",
  "Cancel": "Abbrechen",
  "Name is required": "Name ist erforderlich",
  "Prompt template should include {{selection}}": "Die Vorlage sollte {{selection}} enthalten",
  "Save": "Speichern",
  "Name": "Name",
  "Icon": "Symbol",
  "Prompt Template": "Vorlagen-Template",
  "Explain this: {{selection}}": "Erkläre das: {{selection}}",
  "New": "Neu",
  "Always display floating window, disable sidebar for all site adapters": "Immer das schwebende Fenster anzeigen, die Seitenleiste für alle Website-Adapter deaktivieren",
  "Allow ESC to close all floating windows": "ESC-Taste zum Schließen aller schwebenden Fenster zulassen",
  "Export All Data": "Alle Daten exportieren",
  "Import All Data": "Alle Daten importieren",
  "Keep-Alive Time": "Keep-Alive-Zeit",
  "5m": "5m",
  "30m": "30m",
  "Forever": "Für immer",
  "You have successfully logged in for ChatGPTBox and can now return": "Sie haben sich erfolgreich für ChatGPTBox angemeldet und können jetzt zurückkehren",
  "Claude.ai is not available in your region": "Claude.ai ist in Ihrer Region nicht verfügbar",
  "Claude.ai (Web)": "Claude.ai (Web)",
  "Kimi.Moonshot (Web)": "Kimi.Moonshot (Web)",
  "Bing (Web)": "Bing (Web)",
  "Gemini (Web)": "Gemini (Web)",
  "Type": "Typ",
  "Mode": "Modus",
  "Custom": "Benutzerdefiniert",
  "OpenAI (API)": "OpenAI (API)",
  "Anthropic (API)": "Anthropic (API)",
  "Azure OpenAI (API)": "Azure OpenAI (API)",
  "OpenAI (GPT-3.5-turbo-16k)": "OpenAI (GPT-3.5-turbo-16k)",
  "OpenAI (GPT-4o, 128k)": "OpenAI (GPT-4o, 128k)",
  "OpenAI (GPT-4o mini)": "OpenAI (GPT-4o mini)",
  "OpenAI (GPT-4-Turbo 128k)": "OpenAI (GPT-4-Turbo 128k)",
  "OpenAI (GPT-4-Turbo 128k Preview)": "OpenAI (GPT-4-Turbo 128k Preview)",
  "OpenAI (GPT-4-Turbo 128k 1106 Preview)": "OpenAI (GPT-4-Turbo 128k 1106 Preview)",
  "OpenAI (GPT-4-Turbo 128k 0125 Preview)": "OpenAI (GPT-4-Turbo 128k 0125 Preview)",
  "OpenAI (GPT-5 latest)": "OpenAI (GPT-5 latest)",
  "OpenAI (GPT-5.1 latest)": "OpenAI (GPT-5.1 latest)",
  "OpenAI (GPT-4.1)": "OpenAI (GPT-4.1)",
  "OpenAI (GPT-4.1 mini)": "OpenAI (GPT-4.1 mini)",
  "OpenAI (GPT-4.1 nano)": "OpenAI (GPT-4.1 nano)",
  "Anthropic (Claude 3 Haiku)": "Anthropic (Claude 3 Haiku)",
  "Anthropic (Claude 3.5 Haiku)": "Anthropic (Claude 3.5 Haiku)",
  "Anthropic (Claude 3.7 Sonnet)": "Anthropic (Claude 3.7 Sonnet)",
  "Anthropic (Claude Opus 4)": "Anthropic (Claude Opus 4)",
  "Anthropic (Claude Opus 4.1)": "Anthropic (Claude Opus 4.1)",
  "Anthropic (Claude Opus 4.5)": "Anthropic (Claude Opus 4.5)",
  "Anthropic (Claude Opus 4.6)": "Anthropic (Claude Opus 4.6)",
  "Anthropic (Claude Sonnet 4)": "Anthropic (Claude Sonnet 4)",
  "Anthropic (Claude Sonnet 4.5)": "Anthropic (Claude Sonnet 4.5)",
  "Anthropic (Claude Haiku 4.5)": "Anthropic (Claude Haiku 4.5)",
  "OpenAI (GPT-3.5-turbo 1106)": "OpenAI (GPT-3.5-turbo 1106)",
  "OpenAI (GPT-3.5-turbo 0125)": "OpenAI (GPT-3.5-turbo 0125)",
  "OpenAI (GPT-4-8k 0613)": "OpenAI (GPT-4-8k 0613)",
  "Azure OpenAI": "Azure OpenAI",
  "OpenAI (GPT-5)": "OpenAI (GPT-5)",
  "OpenAI (GPT-5.1)": "OpenAI (GPT-5.1)",
  "OpenAI (GPT-5.2 latest)": "OpenAI (GPT-5.2 latest)",
  "OpenAI (GPT-5.2)": "OpenAI (GPT-5.2)",
  "OpenAI (GPT-5.3 latest)": "OpenAI (GPT-5.3 latest)",
  "OpenAI (GPT-5.4)": "OpenAI (GPT-5.4)",
  "OpenAI (GPT-5.4 mini)": "OpenAI (GPT-5.4 mini)",
  "OpenAI (GPT-5.4 nano)": "OpenAI (GPT-5.4 nano)",
  "Anthropic (Claude Sonnet 4.6)": "Anthropic (Claude Sonnet 4.6)"
}


================================================
FILE: src/_locales/en/main.json
================================================
{
  "General": "General",
  "Selection Tools": "Selection Tools",
  "Sites": "Sites",
  "Advanced": "Advanced",
  "Donate": "Donate",
  "Triggers": "Triggers",
  "Theme": "Theme",
  "API Mode": "API Mode",
  "Get": "Get",
  "Preferred Language": "Preferred Language",
  "Insert ChatGPT at the top of search results": "Insert ChatGPT at the top of search results",
  "Lock scrollbar while answering": "Lock scrollbar while answering",
  "Current Version": "Current Version",
  "Latest": "Latest",
  "Help | Changelog ": "Help | Changelog ",
  "Custom ChatGPT Web API Url": "Custom ChatGPT Web API Url",
  "Custom ChatGPT Web API Path": "Custom ChatGPT Web API Path",
  "Custom OpenAI API Url": "Custom OpenAI API Url",
  "Custom Site Regex": "Custom Site Regex",
  "Exclusively use Custom Site Regex for website matching, ignoring built-in rules": "Exclusively use Custom Site Regex for website matching, ignoring built-in rules",
  "Input Query": "Input Query",
  "Append Query": "Append Query",
  "Prepend Query": "Prepend Query",
  "Wechat Pay": "Wechat Pay",
  "Type your question here\nEnter to send, shift + enter to break line": "Type your question here\nEnter to send\nShift + enter to break line",
  "Type your question here\nEnter to stop generating\nShift + enter to break line": "Type your question here\nEnter to stop generating\nShift + enter to break line",
  "Ask ChatGPT": "Ask ChatGPT",
  "No Input Found": "No Input Found",
  "You": "You",
  "Collapse": "Collapse",
  "Expand": "Expand",
  "Stop": "Stop",
  "Continue on official website": "Continue on official website",
  "Error": "Error",
  "Copy": "Copy",
  "Question": "Question",
  "Answer": "Answer",
  "Waiting for response...": "Waiting for response...",
  "Close the Window": "Close the Window",
  "Pin the Window": "Pin the Window",
  "Float the Window": "Float the Window",
  "Save Conversation": "Save Conversation",
  "UNAUTHORIZED": "UNAUTHORIZED",
  "Please login at https://chatgpt.com first": "Please login at https://chatgpt.com first",
  "Please login at https://claude.ai first, and then click the retry button": "Please login at https://claude.ai first, and then click the retry button",
  "Please login at https://bing.com first": "Please login at https://bing.com first",
  "Then open https://chatgpt.com/api/auth/session": "Then open https://chatgpt.com/api/auth/session",
  "And refresh this page or type you question again": "And click the retry button in the top right corner",
  "Consider creating an api key at https://platform.openai.com/account/api-keys": "Consider creating an api key at https://platform.openai.com/account/api-keys",
  "OpenAI Security Check Required": "OpenAI Security Check Required",
  "Please open https://chatgpt.com/api/auth/session": "Please open https://chatgpt.com/api/auth/session",
  "Please open https://chatgpt.com": "Please open https://chatgpt.com",
  "New Chat": "New Chat",
  "Summarize Page": "Summarize Page",
  "Translate": "Translate",
  "Translate (Bidirectional)": "Translate (Bidirectional)",
  "Translate (To English)": "Translate (To English)",
  "Translate (To Chinese)": "Translate (To Chinese)",
  "Summary": "Summary",
  "Polish": "Polish",
  "Sentiment Analysis": "Sentiment Analysis",
  "Divide Paragraphs": "Divide Paragraphs",
  "Code Explain": "Code Explain",
  "Ask": "Ask",
  "Always": "Always",
  "Manually": "Manually",
  "When query ends with question mark (?)": "When query ends with question mark (?)",
  "Light": "Light",
  "Dark": "Dark",
  "Auto": "Auto",
  "ChatGPT (Web)": "ChatGPT (Web)",
  "ChatGPT (Web, GPT-4)": "ChatGPT (Web, GPT-4)",
  "Bing (Web, GPT-4)": "Bing (Web, GPT-4)",
  "ChatGPT (GPT-3.5-turbo)": "ChatGPT (GPT-3.5-turbo)",
  "OpenAI (GPT-3.5-turbo)": "OpenAI (GPT-3.5-turbo)",
  "ChatGPT (GPT-4-8k)": "ChatGPT (GPT-4-8k)",
  "OpenAI (GPT-4-8k)": "OpenAI (GPT-4-8k)",
  "ChatGPT (GPT-4-32k)": "ChatGPT (GPT-4-32k)",
  "GPT-3.5": "GPT-3.5",
  "Custom Model": "Custom Model",
  "Balanced": "Balanced",
  "Creative": "Creative",
  "Precise": "Precise",
  "Fast": "Fast",
  "API Key": "API Key",
  "Model Name": "Model Name",
  "Custom Model API Url": "Custom Model API Url",
  "Loading...": "Loading...",
  "Feedback": "Feedback",
  "Confirm": "Confirm",
  "Clear Conversation": "Clear Conversation",
  "Retry": "Retry",
  "Exceeded maximum context length": "Exceeded maximum context length, please clear the conversation and try again",
  "Regenerate the answer after switching model": "Regenerate the answer after switching model",
  "Pin": "Pin",
  "Unpin": "Unpin",
  "Delete Conversation": "Delete Conversation",
  "Clear conversations": "Clear conversations",
  "Settings": "Settings",
  "Feature Pages": "Feature Pages",
  "Keyboard Shortcuts": "Keyboard Shortcuts",
  "Open Conversation Page": "Open Conversation Page",
  "Open Conversation Window": "Open Conversation Window",
  "Store to Independent Conversation Page": "Store to Independent Conversation Page",
  "Keep Conversation Window in Background": "Keep conversation window in background, so that you can use shortcut keys to call it up in any program",
  "Max Response Token Length": "Max Response Token Length",
  "Max Conversation Length": "Max Conversation Length",
  "Always pin the floating window": "Always pin the floating window",
  "Export": "Export",
  "Always Create New Conversation Window": "Always Create New Conversation Window",
  "Please keep this tab open. You can now use the web mode of ChatGPTBox": "Please keep this tab open. You can now use the web mode of ChatGPTBox",
  "Go Back": "Go Back",
  "Pin Tab": "Pin Tab",
  "Modules": "Modules",
  "API Params": "API Params",
  "API Url": "API Url",
  "Others": "Others",
  "API Modes": "API Modes",
  "Disable web mode history for better privacy protection, but it will result in unavailable conversations after a period of time": "Disable web mode history for better privacy protection, but it will result in unavailable conversations after a period of time",
  "Display selection tools next to input box to avoid blocking": "Display selection tools next to input box to avoid blocking",
  "Close All Chats In This Page": "Close All Chats In This Page",
  "When Icon Clicked": "When Icon Clicked",
  "Open Settings": "Open Settings",
  "Focus to input box after answering": "Focus to input box after answering",
  "Bing CaptchaChallenge": "You must pass Bing's verification. Please go to https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx and send a message",
  "Exceeded quota": "You exceeded your current quota, check https://platform.openai.com/account/usage",
  "Rate limit": "Rate limit exceeded",
  "Jump to bottom": "Jump to bottom",
  "Explain": "Explain",
  "Failed to get arkose token.": "Failed to get arkose token.",
  "Please keep https://chatgpt.com open and try again. If it still doesn't work, type some characters in the input box of chatgpt web page and try again.": "Please keep https://chatgpt.com open and try again. If it still doesn't work, type some characters in the input box of chatgpt web page and try again.",
  "Open Side Panel": "Open Side Panel",
  "Generating...": "Generating...",
  "moonshot token required, please login at https://kimi.com first, and then click the retry button": "moonshot token required, please login at https://kimi.com first, and then click the retry button",
  "Hide context menu of this extension": "Hide context menu of this extension",
  "Custom Anthropic API Url": "Custom Anthropic API Url",
  "Anthropic API Key": "Anthropic API Key",
  "Cancel": "Cancel",
  "Name is required": "Name is required",
  "Prompt template should include {{selection}}": "Prompt template should include {{selection}}",
  "Save": "Save",
  "Name": "Name",
  "Icon": "Icon",
  "Prompt Template": "Prompt Template",
  "Explain this: {{selection}}": "Explain this: {{selection}}",
  "New": "New",
  "Always display floating window, disable sidebar for all site adapters": "Always display floating window, disable sidebar for all site adapters",
  "Allow ESC to close all floating windows": "Allow ESC to close all floating windows",
  "Export All Data": "Export All Data",
  "Import All Data": "Import All Data",
  "Keep-Alive Time": "Keep-Alive Time",
  "5m": "5m",
  "30m": "30m",
  "Forever": "Forever",
  "You have successfully logged in for ChatGPTBox and can now return": "You have successfully logged in for ChatGPTBox and can now return",
  "Claude.ai is not available in your region": "Claude.ai is not available in your region",
  "Claude.ai (Web)": "Claude.ai (Web)",
  "Kimi.Moonshot (Web)": "Kimi.Moonshot (Web)",
  "Bing (Web)": "Bing (Web)",
  "Gemini (Web)": "Gemini (Web)",
  "Type": "Type",
  "Mode": "Mode",
  "Custom": "Custom",
  "Crop Text to ensure the input tokens do not exceed the model's limit": "Crop Text to ensure the input tokens do not exceed the model's limit",
  "OpenAI (API)": "OpenAI (API)",
  "Anthropic (API)": "Anthropic (API)",
  "Azure OpenAI (API)": "Azure OpenAI (API)",
  "OpenAI (GPT-3.5-turbo-16k)": "OpenAI (GPT-3.5-turbo-16k)",
  "OpenAI (GPT-4o, 128k)": "OpenAI (GPT-4o, 128k)",
  "OpenAI (GPT-4o mini)": "OpenAI (GPT-4o mini)",
  "OpenAI (GPT-4-Turbo 128k)": "OpenAI (GPT-4-Turbo 128k)",
  "OpenAI (GPT-4-Turbo 128k Preview)": "OpenAI (GPT-4-Turbo 128k Preview)",
  "OpenAI (GPT-4-Turbo 128k 1106 Preview)": "OpenAI (GPT-4-Turbo 128k 1106 Preview)",
  "OpenAI (GPT-4-Turbo 128k 0125 Preview)": "OpenAI (GPT-4-Turbo 128k 0125 Preview)",
  "OpenAI (GPT-5 latest)": "OpenAI (GPT-5 latest)",
  "OpenAI (GPT-5.1 latest)": "OpenAI (GPT-5.1 latest)",
  "OpenAI (GPT-4.1)": "OpenAI (GPT-4.1)",
  "OpenAI (GPT-4.1 mini)": "OpenAI (GPT-4.1 mini)",
  "OpenAI (GPT-4.1 nano)": "OpenAI (GPT-4.1 nano)",
  "Anthropic (Claude 3 Haiku)": "Anthropic (Claude 3 Haiku)",
  "Anthropic (Claude 3.5 Haiku)": "Anthropic (Claude 3.5 Haiku)",
  "Anthropic (Claude 3.7 Sonnet)": "Anthropic (Claude 3.7 Sonnet)",
  "Anthropic (Claude Opus 4)": "Anthropic (Claude Opus 4)",
  "Anthropic (Claude Opus 4.1)": "Anthropic (Claude Opus 4.1)",
  "Anthropic (Claude Opus 4.5)": "Anthropic (Claude Opus 4.5)",
  "Anthropic (Claude Opus 4.6)": "Anthropic (Claude Opus 4.6)",
  "Anthropic (Claude Sonnet 4)": "Anthropic (Claude Sonnet 4)",
  "Anthropic (Claude Sonnet 4.5)": "Anthropic (Claude Sonnet 4.5)",
  "Anthropic (Claude Haiku 4.5)": "Anthropic (Claude Haiku 4.5)",
  "OpenAI (GPT-3.5-turbo 1106)": "OpenAI (GPT-3.5-turbo 1106)",
  "OpenAI (GPT-3.5-turbo 0125)": "OpenAI (GPT-3.5-turbo 0125)",
  "OpenAI (GPT-4-8k 0613)": "OpenAI (GPT-4-8k 0613)",
  "Azure OpenAI": "Azure OpenAI",
  "OpenAI (GPT-5)": "OpenAI (GPT-5)",
  "OpenAI (GPT-5.1)": "OpenAI (GPT-5.1)",
  "OpenAI (GPT-5.2 latest)": "OpenAI (GPT-5.2 latest)",
  "OpenAI (GPT-5.2)": "OpenAI (GPT-5.2)",
  "OpenAI (GPT-5.3 latest)": "OpenAI (GPT-5.3 latest)",
  "OpenAI (GPT-5.4)": "OpenAI (GPT-5.4)",
  "OpenAI (GPT-5.4 mini)": "OpenAI (GPT-5.4 mini)",
  "OpenAI (GPT-5.4 nano)": "OpenAI (GPT-5.4 nano)",
  "Anthropic (Claude Sonnet 4.6)": "Anthropic (Claude Sonnet 4.6)"
}


================================================
FILE: src/_locales/es/main.json
================================================
{
  "General": "General",
  "Selection Tools": "Herramientas de selección",
  "Sites": "Adaptaciones de sitios",
  "Advanced": "Avanzado",
  "Donate": "Donar",
  "Triggers": "Disparadores",
  "Theme": "Tema",
  "API Mode": "Modo API",
  "Get": "Obtener",
  "Preferred Language": "Idioma preferido",
  "Insert ChatGPT at the top of search results": "Insertar ChatGPT en la parte superior de los resultados de búsqueda",
  "Lock scrollbar while answering": "Bloquear barra de desplazamiento mientras se responde",
  "Current Version": "Versión actual",
  "Latest": "Última",
  "Help | Changelog ": "Ayuda | Registro de cambios ",
  "Custom ChatGPT Web API Url": "URL personalizada de la API web de ChatGPT",
  "Custom ChatGPT Web API Path": "Ruta personalizada de la API web de ChatGPT",
  "Custom OpenAI API Url": "URL personalizada de la API de OpenAI",
  "Custom Site Regex": "Expresión regular personalizada del sitio",
  "Exclusively use Custom Site Regex for website matching, ignoring built-in rules": "Utilice exclusivamente expesiones regulares personalizadas para la coincidencia de sitios web, ignorando las reglas integradas",
  "Input Query": "Consulta de entrada",
  "Append Query": "Añadir consulta",
  "Prepend Query": "Insertar consulta",
  "Wechat Pay": "Pago de Wechat",
  "Type your question here\nEnter to send, shift + enter to break line": "Escriba su pregunta aquí\nPresione Enter para enviar, Shift+Enter para saltar de línea",
  "Type your question here\nEnter to stop generating\nShift + enter to break line": "Escriba su pregunta aquí\nPresione Enter para detener la generación\nShift + Enter para saltar de línea",
  "Ask ChatGPT": "Preguntar a ChatGPT",
  "No Input Found": "No se encontró entrada",
  "You": "Tú",
  "Collapse": "Colapsar",
  "Expand": "Expandir",
  "Stop": "Detener",
  "Continue on official website": "Continuar en el sitio web oficial",
  "Error": "Error",
  "Copy": "Copiar",
  "Question": "Pregunta",
  "Answer": "Respuesta",
  "Waiting for response...": "Esperando respuesta...",
  "Close the Window": "Cerrar ventana",
  "Pin the Window": "Fijar ventana",
  "Float the Window": "Ventana flotante",
  "Save Conversation": "Guardar conversación",
  "UNAUTHORIZED": "NO AUTORIZADO",
  "Please login at https://chatgpt.com first": "Por favor, inicie sesión en https://chatgpt.com primero",
  "Please login at https://claude.ai first, and then click the retry button": "Por favor, inicie sesión en https://claude.ai primero, y luego haga clic en el botón Reintentar",
  "Please login at https://bing.com first": "Por favor, inicie sesión en https://bing.com primero",
  "Then open https://chatgpt.com/api/auth/session": "Luego abra https://chatgpt.com/api/auth/session",
  "And refresh this page or type you question again": "A continuación, pulse el botón Reintentar situado en la esquina superior derecha.",
  "Consider creating an api key at https://platform.openai.com/account/api-keys": "Considere crear una clave de API en https://platform.openai.com/account/api-keys",
  "OpenAI Security Check Required": "Se requiere una comprobación de seguridad de OpenAI",
  "Please open https://chatgpt.com/api/auth/session": "Por favor, abra https://chatgpt.com/api/auth/session",
  "Please open https://chatgpt.com": "Por favor, abra https://chatgpt.com",
  "New Chat": "Nuevo chat",
  "Summarize Page": "Resumir página",
  "Translate": "Traducir",
  "Translate (Bidirectional)": "Traducir (Bidireccional)",
  "Translate (To English)": "Traducir (Al Inglés)",
  "Translate (To Chinese)": "Traducir (Al Chino)",
  "Summary": "Resumen",
  "Polish": "Pulir",
  "Sentiment Analysis": "Análisis de sentimientos",
  "Divide Paragraphs": "Dividir párrafos",
  "Code Explain": "Explicación de código",
  "Ask": "Preguntar",
  "Always": "Siempre",
  "Manually": "Manualmente",
  "When query ends with question mark (?)": "Cuando la consulta termina con signo de pregunta (?)",
  "Light": "Claro",
  "Dark": "Oscuro",
  "Auto": "Automático",
  "ChatGPT (Web)": "ChatGPT (Web)",
  "ChatGPT (Web, GPT-4)": "ChatGPT (Web, GPT-4)",
  "Bing (Web, GPT-4)": "Bing (Web, GPT-4)",
  "ChatGPT (GPT-3.5-turbo)": "ChatGPT (GPT-3.5-turbo)",
  "OpenAI (GPT-3.5-turbo)": "OpenAI (GPT-3.5-turbo)",
  "ChatGPT (GPT-4-8k)": "ChatGPT (GPT-4-8k)",
  "OpenAI (GPT-4-8k)": "OpenAI (GPT-4-8k)",
  "ChatGPT (GPT-4-32k)": "ChatGPT (GPT-4-32k)",
  "GPT-3.5": "GPT-3.5",
  "Custom Model": "Modelo personalizado",
  "Balanced": "Equilibrado",
  "Creative": "Creativo",
  "Precise": "Preciso",
  "Fast": "Rápido",
  "API Key": "Clave de API",
  "Model Name": "Nombre del modelo",
  "Custom Model API Url": "URL de la API de modelo personalizada",
  "Loading...": "Cargando...",
  "Feedback": "Comentarios",
  "Confirm": "Confirmar",
  "Clear Conversation": "Borrar conversación",
  "Retry": "Reintentar",
  "Exceeded maximum context length": "Se superó la longitud máxima del contexto, borre la conversación y vuelva a intentarlo",
  "Regenerate the answer after switching model": "Regenerar la respuesta después de cambiar el modelo",
  "Pin": "Fijar",
  "Unpin": "Desfijar",
  "Delete Conversation": "Eliminar conversación",
  "Clear conversations": "Borrar todas las conversaciones",
  "Settings": "Configuración",
  "Feature Pages": "Páginas de características",
  "Keyboard Shortcuts": "Atajos de teclado",
  "Open Conversation Page": "Abrir página de conversación independiente",
  "Open Conversation Window": "Abrir la ventana de conversación independiente",
  "Store to Independent Conversation Page": "Guardar en página de conversación independiente",
  "Keep Conversation Window in Background": "Mantener la ventana de conversación en segundo plano para poder acceder a ella desde cualquier aplicación mediante accesos directos.",
  "Max Response Token Length": "Longitud máxima de tokens de respuesta",
  "Max Conversation Length": "Longitud máxima de conversación",
  "Always pin the floating window": "Siempre fijar la ventana flotante",
  "Export": "Exportar",
  "Always Create New Conversation Window": "Siempre crear una nueva ventana de conversación",
  "Please keep this tab open. You can now use the web mode of ChatGPTBox": "Por favor, mantenga esta pestaña abierta. Ahora puede utilizar el modo web de ChatGPTBox.",
  "Go Back": "Volver",
  "Pin Tab": "Fijar pestaña",
  "Modules": "Módulos",
  "API Params": "Parámetros de la API",
  "API Url": "URL de la API",
  "Others": "Otros",
  "API Modes": "Modos de la API",
  "Disable web mode history for better privacy protection, but it will result in unavailable conversations after a period of time": "Desactivar el historial del modo web para una mejor protección de la privacidad, pero esto resultará en conversaciones no disponibles después de un período de tiempo.",
  "Display selection tools next to input box to avoid blocking": "Mostrar herramientas de selección junto al cuadro de entrada para evitar bloqueos",
  "Close All Chats In This Page": "Cerrar todos los chats en esta página",
  "When Icon Clicked": "Cuando se hace clic en el icono",
  "Open Settings": "Abrir configuración",
  "Focus to input box after answering": "Enfocar en el cuadro de entrada después de responder",
  "Bing CaptchaChallenge": "Desafío de Captcha de Bing: Debe pasar una verificación de Bing. Abra https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx y envíe un mensaje.",
  "Exceeded quota": "Cuota superada: Verifique su saldo o fecha de vencimiento en el siguiente enlace: https://platform.openai.com/account/usage",
  "Rate limit": "Límite de velocidad alcanzado",
  "Jump to bottom": "Saltar al final",
  "Explain": "Explicar",
  "Failed to get arkose token.": "No se pudo obtener el token de arkose.",
  "Please keep https://chatgpt.com open and try again. If it still doesn't work, type some characters in the input box of chatgpt web page and try again.": "Por favor, mantenga https://chatgpt.com abierto e inténtelo de nuevo. Si aún no funciona, escriba algunos caracteres en el cuadro de entrada de la página web de chatgpt e inténtelo de nuevo.",
  "Open Side Panel": "Abrir panel lateral",
  "Generating...": "Generando...",
  "moonshot token required, please login at https://kimi.com first, and then click the retry button": "se requiere un token de moonshot, por favor inicie sesión en https://kimi.com primero, y luego haga clic en el botón Reintentar",
  "Hide context menu of this extension": "Ocultar menú contextual de esta extensión",
  "Custom Anthropic API Url": "URL personalizada de la API de Anthropic",
  "Anthropic API Key": "Clave API de Anthropic",
  "Cancel": "Cancelar",
  "Name is required": "Se requiere un nombre",
  "Prompt template should include {{selection}}": "La plantilla de sugerencias debe incluir {{selection}}",
  "Save": "Guardar",
  "Name": "Nombre",
  "Icon": "Icono",
  "Prompt Template": "Plantilla de sugerencias",
  "Explain this: {{selection}}": "Explicar esto: {{selection}}",
  "New": "Nuevo",
  "Always display floating window, disable sidebar for all site adapters": "Mostrar siempre la ventana flotante, desactivar la barra lateral para todos los adaptadores de sitios",
  "Allow ESC to close all floating windows": "Permitir que ESC cierre todas las ventanas flotantes",
  "Export All Data": "Exportar todos los datos",
  "Import All Data": "Importar todos los datos",
  "Keep-Alive Time": "Tiempo de mantenimiento de la conexión",
  "5m": "5m",
  "30m": "30m",
  "Forever": "Siempre",
  "You have successfully logged in for ChatGPTBox and can now return": "Ha iniciado sesión correctamente en ChatGPTBox y ahora puede regresar",
  "Claude.ai is not available in your region": "Claude.ai no está disponible en su región",
  "Claude.ai (Web)": "Claude.ai (Web)",
  "Kimi.Moonshot (Web)": "Kimi.Moonshot (Web)",
  "Bing (Web)": "Bing (Web)",
  "Gemini (Web)": "Gemini (Web)",
  "Type": "Tipo",
  "Mode": "Modo",
  "Custom": "Personalizado",
  "OpenAI (API)": "OpenAI (API)",
  "Anthropic (API)": "Anthropic (API)",
  "Azure OpenAI (API)": "Azure OpenAI (API)",
  "OpenAI (GPT-3.5-turbo-16k)": "OpenAI (GPT-3.5-turbo-16k)",
  "OpenAI (GPT-4o, 128k)": "OpenAI (GPT-4o, 128k)",
  "OpenAI (GPT-4o mini)": "OpenAI (GPT-4o mini)",
  "OpenAI (GPT-4-Turbo 128k)": "OpenAI (GPT-4-Turbo 128k)",
  "OpenAI (GPT-4-Turbo 128k Preview)": "OpenAI (GPT-4-Turbo 128k Preview)",
  "OpenAI (GPT-4-Turbo 128k 1106 Preview)": "OpenAI (GPT-4-Turbo 128k 1106 Preview)",
  "OpenAI (GPT-4-Turbo 128k 0125 Preview)": "OpenAI (GPT-4-Turbo 128k 0125 Preview)",
  "OpenAI (GPT-5 latest)": "OpenAI (GPT-5 latest)",
  "OpenAI (GPT-5.1 latest)": "OpenAI (GPT-5.1 latest)",
  "OpenAI (GPT-4.1)": "OpenAI (GPT-4.1)",
  "OpenAI (GPT-4.1 mini)": "OpenAI (GPT-4.1 mini)",
  "OpenAI (GPT-4.1 nano)": "OpenAI (GPT-4.1 nano)",
  "Anthropic (Claude 3 Haiku)": "Anthropic (Claude 3 Haiku)",
  "Anthropic (Claude 3.5 Haiku)": "Anthropic (Claude 3.5 Haiku)",
  "Anthropic (Claude 3.7 Sonnet)": "Anthropic (Claude 3.7 Sonnet)",
  "Anthropic (Claude Opus 4)": "Anthropic (Claude Opus 4)",
  "Anthropic (Claude Opus 4.1)": "Anthropic (Claude Opus 4.1)",
  "Anthropic (Claude Opus 4.5)": "Anthropic (Claude Opus 4.5)",
  "Anthropic (Claude Opus 4.6)": "Anthropic (Claude Opus 4.6)",
  "Anthropic (Claude Sonnet 4)": "Anthropic (Claude Sonnet 4)",
  "Anthropic (Claude Sonnet 4.5)": "Anthropic (Claude Sonnet 4.5)",
  "Anthropic (Claude Haiku 4.5)": "Anthropic (Claude Haiku 4.5)",
  "OpenAI (GPT-3.5-turbo 1106)": "OpenAI (GPT-3.5-turbo 1106)",
  "OpenAI (GPT-3.5-turbo 0125)": "OpenAI (GPT-3.5-turbo 0125)",
  "OpenAI (GPT-4-8k 0613)": "OpenAI (GPT-4-8k 0613)",
  "Azure OpenAI": "Azure OpenAI",
  "OpenAI (GPT-5)": "OpenAI (GPT-5)",
  "OpenAI (GPT-5.1)": "OpenAI (GPT-5.1)",
  "OpenAI (GPT-5.2 latest)": "OpenAI (GPT-5.2 latest)",
  "OpenAI (GPT-5.2)": "OpenAI (GPT-5.2)",
  "OpenAI (GPT-5.3 latest)": "OpenAI (GPT-5.3 latest)",
  "OpenAI (GPT-5.4)": "OpenAI (GPT-5.4)",
  "OpenAI (GPT-5.4 mini)": "OpenAI (GPT-5.4 mini)",
  "OpenAI (GPT-5.4 nano)": "OpenAI (GPT-5.4 nano)",
  "Anthropic (Claude Sonnet 4.6)": "Anthropic (Claude Sonnet 4.6)"
}


================================================
FILE: src/_locales/fr/main.json
================================================
{
  "General": "Général",
  "Selection Tools": "Outils de sélection",
  "Sites": "Sites",
  "Advanced": "Avancé",
  "Donate": "Faire un don",
  "Triggers": "Déclencheurs",
  "Theme": "Thème",
  "API Mode": "Mode API",
  "Get": "Obtenir",
  "Preferred Language": "Langue préférée",
  "Insert ChatGPT at the top of search results": "Insérer ChatGPT en haut des résultats de recherche",
  "Lock scrollbar while answering": "Verrouiller la barre de défilement pendant la réponse",
  "Current Version": "Version actuelle",
  "Latest": "Le plus récent",
  "Help | Changelog ": "Aide | Journal des modifications",
  "Custom ChatGPT Web API Url": "URL web API personnalisée ChatGPT",
  "Custom ChatGPT Web API Path": "Chemin d'accès à l'API Web ChatGPT personnalisée",
  "Custom OpenAI API Url": "URL de l'API OpenAI personnalisée",
  "Custom Site Regex": "Expression régulière de site personnalisée",
  "Exclusively use Custom Site Regex for website matching, ignoring built-in rules": "Utiliser exclusivement l'expression régulière de site personnalisée pour la correspondance de site Web, en ignorant les règles intégrées",
  "Input Query": "Sélecteur d'entrée",
  "Append Query": "Sélecteur à ajouter",
  "Prepend Query": "Sélecteur à insérer",
  "Wechat Pay": "Paiement Wechat",
  "Type your question here\nEnter to send, shift + enter to break line": "Tapez votre question ici\nAppuyez sur entrée pour envoyer, shift+entrée pour passer à la ligne suivante",
  "Type your question here\nEnter to stop generating\nShift + enter to break line": "Tapez votre question ici\nAppuyez sur Entrée pour arrêter la génération\nShift + Entrée pour passer à la ligne suivante",
  "Ask ChatGPT": "Demander à ChatGPT",
  "No Input Found": "Aucune entrée trouvée",
  "You": "Vous",
  "Collapse": "Réduire",
  "Expand": "Agrandir",
  "Stop": "Arrêter",
  "Continue on official website": "Continuer sur le site officiel",
  "Error": "Erreur",
  "Copy": "Copier",
  "Question": "Question",
  "Answer": "Réponse",
  "Waiting for response...": "En attente de réponse...",
  "Close the Window": "Fermer la fenêtre",
  "Pin the Window": "Épingler la fenêtre",
  "Float the Window": "Flotter la fenêtre",
  "Save Conversation": "Enregistrer la conversation",
  "UNAUTHORIZED": "NON AUTORISÉ",
  "Please login at https://chatgpt.com first": "Veuillez vous connecter d'abord sur https://chatgpt.com",
  "Please login at https://claude.ai first, and then click the retry button": "Veuillez vous connecter d'abord sur https://claude.ai, puis cliquez sur le bouton Réessayer",
  "Please login at https://bing.com first": "Veuillez vous connecter d'abord sur https://bing.com",
  "Then open https://chatgpt.com/api/auth/session": "Puis ouvrez https://chatgpt.com/api/auth/session",
  "And refresh this page or type you question again": "Cliquez ensuite sur le bouton Réessayer dans le coin supérieur droit",
  "Consider creating an api key at https://platform.openai.com/account/api-keys": "Pensez à créer une clé API sur https://platform.openai.com/account/api-keys",
  "OpenAI Security Check Required": "Vérification de sécurité OpenAI requise",
  "Please open https://chatgpt.com/api/auth/session": "Veuillez ouvrir https://chatgpt.com/api/auth/session",
  "Please open https://chatgpt.com": "Veuillez ouvrir https://chatgpt.com",
  "New Chat": "Nouveau chat",
  "Summarize Page": "Résumer la page",
  "Translate": "Traduire",
  "Translate (Bidirectional)": "Traduire (Bidirectionnel)",
  "Translate (To English)": "Traduire (Vers l'anglais)",
  "Translate (To Chinese)": "Traduire (Vers le chinois)",
  "Summary": "Résumé",
  "Polish": "Peaufiner",
  "Sentiment Analysis": "Analyse de sentiment",
  "Divide Paragraphs": "Diviser les paragraphes",
  "Code Explain": "Expliquer le code",
  "Ask": "Demander",
  "Always": "Toujours",
  "Manually": "Manuellement",
  "When query ends with question mark (?)": "Lorsque la requête se termine par un point d'interrogation (?)",
  "Light": "Clair",
  "Dark": "Sombre",
  "Auto": "Automatique",
  "ChatGPT (Web)": "ChatGPT (Web)",
  "ChatGPT (Web, GPT-4)": "ChatGPT (Web, GPT-4)",
  "Bing (Web, GPT-4)": "Bing (Web, GPT-4)",
  "ChatGPT (GPT-3.5-turbo)": "ChatGPT (GPT-3.5-turbo)",
  "OpenAI (GPT-3.5-turbo)": "OpenAI (GPT-3.5-turbo)",
  "ChatGPT (GPT-4-8k)": "ChatGPT (GPT-4-8k)",
  "OpenAI (GPT-4-8k)": "OpenAI (GPT-4-8k)",
  "ChatGPT (GPT-4-32k)": "ChatGPT (GPT-4-32k)",
  "GPT-3.5": "GPT-3.5",
  "Custom Model": "Modèle personnalisé",
  "Balanced": "Équilibré",
  "Creative": "Créatif",
  "Precise": "Précis",
  "Fast": "Rapide",
  "API Key": "Clé API",
  "Model Name": "Nom du modèle",
  "Custom Model API Url": "URL API personnalisée du modèle",
  "Loading...": "Chargement...",
  "Feedback": "Commentaires",
  "Confirm": "Confirmer",
  "Clear Conversation": "Effacer la conversation",
  "Retry": "Réessayer",
  "Exceeded maximum context length": "Dépassement de la longueur maximale de contexte, veuillez effacer la conversation et réessayer",
  "Regenerate the answer after switching model": "Régénérer la réponse après avoir changé de modèle",
  "Pin": "Épingler",
  "Unpin": "Détacher",
  "Delete Conversation": "Supprimer la conversation",
  "Clear conversations": "Effacer les conversations",
  "Settings": "Paramètres",
  "Feature Pages": "Pages de fonctionnalités",
  "Keyboard Shortcuts": "Raccourcis clavier",
  "Open Conversation Page": "Ouvrir la page de conversation",
  "Open Conversation Window": "Ouvrir la fenêtre de conversation",
  "Store to Independent Conversation Page": "Enregistrer sur une page de conversation indépendante",
  "Keep Conversation Window in Background": "Gardez la fenêtre de conversation en arrière-plan pour l'appeler avec des raccourcis dans n'importe quelle application",
  "Max Response Token Length": "Longueur maximale des jetons de réponse",
  "Max Conversation Length": "Longueur maximale de la conversation",
  "Always pin the floating window": "Épingler toujours la fenêtre flottante",
  "Export": "Exporter",
  "Always Create New Conversation Window": "Créer toujours une nouvelle fenêtre de conversation",
  "Please keep this tab open. You can now use the web mode of ChatGPTBox": "Veuillez laisser cette tabulation ouverte. Vous pouvez désormais utiliser le mode web de ChatGPTBox",
  "Go Back": "Retour",
  "Pin Tab": "Épingler l'onglet",
  "Modules": "Modules",
  "API Params": "Paramètres de l'API",
  "API Url": "URL de l'API",
  "Others": "Autres",
  "API Modes": "Modes de l'API",
  "Disable web mode history for better privacy protection, but it will result in unavailable conversations after a period of time": "Désactivez l'historique du mode web pour une meilleure protection de la vie privée, mais cela entraînera des conversations non disponibles après un certain temps",
  "Display selection tools next to input box to avoid blocking": "Afficher des outils de sélection à côté de la boîte de saisie pour éviter de bloquer la vue",
  "Close All Chats In This Page": "Fermer tous les chats sur cette page",
  "When Icon Clicked": "Lorsque l'icône est cliquée",
  "Open Settings": "Ouvrir les paramètres",
  "Focus to input box after answering": "Se concentrer sur la boîte de saisie après avoir répondu",
  "Bing CaptchaChallenge": "Défi Captcha Bing : Vous devez réussir une vérification Bing. Ouvrez https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx et envoyez un message.",
  "Exceeded quota": "Quota dépassé : Vérifiez votre solde ou la date d'expiration à l'adresse suivante: https://platform.openai.com/account/usage",
  "Rate limit": "Limite de taux atteinte",
  "Jump to bottom": "Aller en bas",
  "Explain": "Expliquer",
  "Failed to get arkose token.": "Échec de l'obtention du jeton arkose.",
  "Please keep https://chatgpt.com open and try again. If it still doesn't work, type some characters in the input box of chatgpt web page and try again.": "Veuillez garder https://chatgpt.com ouvert et réessayer. Si cela ne fonctionne toujours pas, tapez quelques caractères dans la boîte de saisie de la page web chatgpt et réessayez.",
  "Open Side Panel": "Ouvrir le panneau latéral",
  "Generating...": "Génération...",
  "moonshot token required, please login at https://kimi.com first, and then click the retry button": "jeton moonshot requis, veuillez vous connecter d'abord sur https://kimi.com, puis cliquez sur le bouton Réessayer",
  "Hide context menu of this extension": "Masquer le menu contextuel de cette extension",
  "Custom Anthropic API Url": "URL API Anthropic personnalisée",
  "Anthropic API Key": "Clé API Anthropic",
  "Cancel": "Annuler",
  "Name is required": "Le nom est requis",
  "Prompt template should include {{selection}}": "Le modèle de suggestion doit inclure {{selection}}",
  "Save": "Enregistrer",
  "Name": "Nom",
  "Icon": "Icône",
  "Prompt Template": "Modèle de suggestion",
  "Explain this: {{selection}}": "Expliquer ceci : {{selection}}",
  "New": "Nouveau",
  "Always display floating window, disable sidebar for all site adapters": "Toujours afficher la fenêtre flottante, désactiver la barre latérale pour tous les adaptateurs de site",
  "Allow ESC to close all floating windows": "Autoriser la touche ESC pour fermer toutes les fenêtres flottantes",
  "Export All Data": "Exporter toutes les données",
  "Import All Data": "Importer toutes les données",
  "Keep-Alive Time": "Temps de maintien de la connexion",
  "5m": "5m",
  "30m": "30m",
  "Forever": "Toujours",
  "You have successfully logged in for ChatGPTBox and can now return": "Vous vous êtes connecté avec succès à ChatGPTBox et pouvez maintenant revenir",
  "Claude.ai is not available in your region": "Claude.ai n'est pas disponible dans votre région",
  "Claude.ai (Web)": "Claude.ai (Web)",
  "Kimi.Moonshot (Web)": "Kimi.Moonshot (Web)",
  "Bing (Web)": "Bing (Web)",
  "Gemini (Web)": "Gemini (Web)",
  "Type": "Type",
  "Mode": "Mode",
  "Custom": "Personnalisé",
  "OpenAI (API)": "OpenAI (API)",
  "Anthropic (API)": "Anthropic (API)",
  "Azure OpenAI (API)": "Azure OpenAI (API)",
  "OpenAI (GPT-3.5-turbo-16k)": "OpenAI (GPT-3.5-turbo-16k)",
  "OpenAI (GPT-4o, 128k)": "OpenAI (GPT-4o, 128k)",
  "OpenAI (GPT-4o mini)": "OpenAI (GPT-4o mini)",
  "OpenAI (GPT-4-Turbo 128k)": "OpenAI (GPT-4-Turbo 128k)",
  "OpenAI (GPT-4-Turbo 128k Preview)": "OpenAI (GPT-4-Turbo 128k Preview)",
  "OpenAI (GPT-4-Turbo 128k 1106 Preview)": "OpenAI (GPT-4-Turbo 128k 1106 Preview)",
  "OpenAI (GPT-4-Turbo 128k 0125 Preview)": "OpenAI (GPT-4-Turbo 128k 0125 Preview)",
  "OpenAI (GPT-5 latest)": "OpenAI (GPT-5 latest)",
  "OpenAI (GPT-5.1 latest)": "OpenAI (GPT-5.1 latest)",
  "OpenAI (GPT-4.1)": "OpenAI (GPT-4.1)",
  "OpenAI (GPT-4.1 mini)": "OpenAI (GPT-4.1 mini)",
  "OpenAI (GPT-4.1 nano)": "OpenAI (GPT-4.1 nano)",
  "Anthropic (Claude 3 Haiku)": "Anthropic (Claude 3 Haiku)",
  "Anthropic (Claude 3.5 Haiku)": "Anthropic (Claude 3.5 Haiku)",
  "Anthropic (Claude 3.7 Sonnet)": "Anthropic (Claude 3.7 Sonnet)",
  "Anthropic (Claude Opus 4)": "Anthropic (Claude Opus 4)",
  "Anthropic (Claude Opus 4.1)": "Anthropic (Claude Opus 4.1)",
  "Anthropic (Claude Opus 4.5)": "Anthropic (Claude Opus 4.5)",
  "Anthropic (Claude Opus 4.6)": "Anthropic (Claude Opus 4.6)",
  "Anthropic (Claude Sonnet 4)": "Anthropic (Claude Sonnet 4)",
  "Anthropic (Claude Sonnet 4.5)": "Anthropic (Claude Sonnet 4.5)",
  "Anthropic (Claude Haiku 4.5)": "Anthropic (Claude Haiku 4.5)",
  "OpenAI (GPT-3.5-turbo 1106)": "OpenAI (GPT-3.5-turbo 1106)",
  "OpenAI (GPT-3.5-turbo 0125)": "OpenAI (GPT-3.5-turbo 0125)",
  "OpenAI (GPT-4-8k 0613)": "OpenAI (GPT-4-8k 0613)",
  "Azure OpenAI": "Azure OpenAI",
  "OpenAI (GPT-5)": "OpenAI (GPT-5)",
  "OpenAI (GPT-5.1)": "OpenAI (GPT-5.1)",
  "OpenAI (GPT-5.2 latest)": "OpenAI (GPT-5.2 latest)",
  "OpenAI (GPT-5.2)": "OpenAI (GPT-5.2)",
  "OpenAI (GPT-5.3 latest)": "OpenAI (GPT-5.3 latest)",
  "OpenAI (GPT-5.4)": "OpenAI (GPT-5.4)",
  "OpenAI (GPT-5.4 mini)": "OpenAI (GPT-5.4 mini)",
  "OpenAI (GPT-5.4 nano)": "OpenAI (GPT-5.4 nano)",
  "Anthropic (Claude Sonnet 4.6)": "Anthropic (Claude Sonnet 4.6)"
}


================================================
FILE: src/_locales/i18n-react.mjs
================================================
import i18n from 'i18next'
import { initReactI18next } from 'react-i18next'
import { resources } from './resources'

i18n.use(initReactI18next).init({
  resources,
  fallbackLng: 'en',
  interpolation: {
    escapeValue: false, // not needed for react as it escapes by default
  },
})


================================================
FILE: src/_locales/i18n.mjs
================================================
import i18n from 'i18next'
import { resources } from './resources'

i18n.init({
  resources,
  fallbackLng: 'en',
})


================================================
FILE: src/_locales/in/main.json
================================================
{
  "General": "Umum",
  "Selection Tools": "Alat Seleksi",
  "Sites": "Situs",
  "Advanced": "Lanjutan",
  "Donate": "Donasi",
  "Triggers": "Pemicu",
  "Theme": "Tema",
  "API Mode": "Mode API",
  "Get": "Dapatkan",
  "Preferred Language": "Bahasa yang Dipilih",
  "Insert ChatGPT at the top of search results": "Masukkan ChatGPT di bagian atas hasil pencarian",
  "Lock scrollbar while answering": "Kunci scrollbar saat menjawab",
  "Current Version": "Versi Saat Ini",
  "Latest": "Terbaru",
  "Help | Changelog ": "Bantuan | Perubahan",
  "Custom ChatGPT Web API Url": "URL Web API ChatGPT Kustom",
  "Custom ChatGPT Web API Path": "Path Web API ChatGPT Kustom",
  "Custom OpenAI API Url": "URL API OpenAI Kustom",
  "Custom Site Regex": "Regex Situs Kustom",
  "Exclusively use Custom Site Regex for website matching, ignoring built-in rules": "Gunakan secara eksklusif Regex Situs Kustom untuk pencocokan situs web, mengabaikan aturan bawaan",
  "Input Query": "Query Masukan",
  "Append Query": "Tambahkan Query",
  "Prepend Query": "Tambahkan Query di Awal",
  "Wechat Pay": "Pembayaran Wechat",
  "Type your question here\nEnter to send, shift + enter to break line": "Ketik pertanyaanmu di sini\nTekan Enter untuk mengirim, Shift + Enter untuk membuat baris baru",
  "Type your question here\nEnter to stop generating\nShift + enter to break line": "Ketik pertanyaanmu di sini\nTekan Enter untuk menghentikan pembuatan\nShift + Enter untuk membuat baris baru",
  "Ask ChatGPT": "Tanyakan ke ChatGPT",
  "No Input Found": "Tidak Ada Input Ditemukan",
  "You": "Anda",
  "Collapse": "Ciutkan",
  "Expand": "Perbesar",
  "Stop": "Berhenti",
  "Continue on official website": "Lanjutkan di situs web resmi",
  "Error": "Kesalahan",
  "Copy": "Salin",
  "Question": "Pertanyaan",
  "Answer": "Jawaban",
  "Waiting for response...": "Menunggu tanggapan...",
  "Close the Window": "Tutup Jendela",
  "Pin the Window": "Sematkan Jendela",
  "Float the Window": "Mengambangkan Jendela",
  "Save Conversation": "Simpan Percakapan",
  "UNAUTHORIZED": "TIDAK DIIZINKAN",
  "Please login at https://chatgpt.com first": "Silakan masuk di https://chatgpt.com terlebih dahulu",
  "Please login at https://claude.ai first, and then click the retry button": "Silakan masuk di https://claude.ai terlebih dahulu, lalu klik tombol coba lagi",
  "Please login at https://bing.com first": "Silakan masuk di https://bing.com terlebih dahulu",
  "Then open https://chatgpt.com/api/auth/session": "Lalu buka https://chatgpt.com/api/auth/session",
  "And refresh this page or type you question again": "Setelah itu klik tombol Coba Lagi di sudut kanan atas",
  "Consider creating an api key at https://platform.openai.com/account/api-keys": "Pertimbangkan untuk membuat kunci API di https://platform.openai.com/account/api-keys",
  "OpenAI Security Check Required": "Diperlukan Pemeriksaan Keamanan OpenAI",
  "Please open https://chatgpt.com/api/auth/session": "Harap buka https://chatgpt.com/api/auth/session",
  "Please open https://chatgpt.com": "Harap buka https://chatgpt.com",
  "New Chat": "Obrolan Baru",
  "Summarize Page": "Ringkasan Halaman",
  "Translate": "Terjemahkan",
  "Translate (Bidirectional)": "Terjemahkan (Dua Arah)",
  "Translate (To English)": "Terjemahkan (Ke Bahasa Inggris)",
  "Translate (To Chinese)": "Terjemahkan (Ke Bahasa Tionghoa)",
  "Summary": "Ringkasan",
  "Polish": "Perbaikan",
  "Sentiment Analysis": "Analisis Sentimen",
  "Divide Paragraphs": "Bagi Paragraf",
  "Code Explain": "Penjelasan Kode",
  "Ask": "Tanya",
  "Always": "Selalu",
  "Manually": "Secara Manual",
  "When query ends with question mark (?)": "Ketika permintaan diakhiri dengan tanda tanya (?)",
  "Light": "Terang",
  "Dark": "Gelap",
  "Auto": "Otomatis",
  "ChatGPT (Web)": "ChatGPT (Web)",
  "ChatGPT (Web, GPT-4)": "ChatGPT (Web, GPT-4)",
  "Bing (Web, GPT-4)": "Bing (Web, GPT-4)",
  "ChatGPT (GPT-3.5-turbo)": "ChatGPT (GPT-3.5-turbo)",
  "OpenAI (GPT-3.5-turbo)": "OpenAI (GPT-3.5-turbo)",
  "ChatGPT (GPT-4-8k)": "ChatGPT (GPT-4-8k)",
  "OpenAI (GPT-4-8k)": "OpenAI (GPT-4-8k)",
  "ChatGPT (GPT-4-32k)": "ChatGPT (GPT-4-32k)",
  "GPT-3.5": "GPT-3.5",
  "Custom Model": "Model Kustom",
  "Balanced": "Seimbang",
  "Creative": "Kreatif",
  "Precise": "Tepat",
  "Fast": "Cepat",
  "API Key": "Kunci API",
  "Model Name": "Nama Model",
  "Custom Model API Url": "URL API Model Kustom",
  "Loading...": "Sedang Memuat...",
  "Feedback": "Masukan",
  "Confirm": "Konfirmasi",
  "Clear Conversation": "Bersihkan Percakapan",
  "Retry": "Coba Lagi",
  "Exceeded maximum context length": "Melampaui batas maksimum panjang konteks, harap bersihkan percakapan dan coba lagi",
  "Regenerate the answer after switching model": "Hasilkan kembali jawaban setelah beralih ke model lain",
  "Pin": "Sematkan",
  "Unpin": "Lepas Sematan",
  "Delete Conversation": "Hapus Percakapan",
  "Clear conversations": "Hapus Percakapan",
  "Settings": "Pengaturan",
  "Feature Pages": "Halaman Fitur",
  "Keyboard Shortcuts": "Pintasan Keyboard",
  "Open Conversation Page": "Buka Halaman Percakapan",
  "Open Conversation Window": "Buka Jendela Percakapan",
  "Store to Independent Conversation Page": "Simpan ke Halaman Percakapan Independen",
  "Keep Conversation Window in Background": "Biarkan jendela percakapan di latar belakang, sehingga Anda dapat menggunakan pintasan keyboard untuk memanggilnya di program mana pun",
  "Max Response Token Length": "Panjang Token Respon Maksimum",
  "Max Conversation Length": "Panjang Percakapan Maksimum",
  "Always pin the floating window": "Selalu selipkan jendela mengambang",
  "Export": "Ekspor",
  "Always Create New Conversation Window": "Selalu Buat Jendela Percakapan Baru",
  "Please keep this tab open. You can now use the web mode of ChatGPTBox": "Silakan tetap buka tab ini. Anda sekarang dapat menggunakan mode web ChatGPTBox",
  "Go Back": "Kembali",
  "Pin Tab": "Sematkan Tab",
  "Modules": "Modul",
  "API Params": "Parameter API",
  "API Url": "URL API",
  "Others": "Lainnya",
  "API Modes": "Mode API",
  "Disable web mode history for better privacy protection, but it will result in unavailable conversations after a period of time": "Nonaktifkan riwayat mode web untuk perlindungan privasi yang lebih baik, tetapi ini akan menyebabkan percakapan tidak tersedia setelah jangka waktu tertentu",
  "Display selection tools next to input box to avoid blocking": "Tampilkan alat pilihan di sebelah kotak masukan untuk menghindari pemblokiran",
  "Close All Chats In This Page": "Tutup Semua Percakapan di Halaman Ini",
  "When Icon Clicked": "Saat Ikon Diklik",
  "Open Settings": "Buka Pengaturan",
  "Focus to input box after answering": "Fokus pada kotak masukan setelah menjawab",
  "Bing CaptchaChallenge": "Anda harus melewati verifikasi Bing. Silakan pergi ke https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx dan kirim pesan",
  "Exceeded quota": "Anda telah melebihi kuota saat ini, periksa https://platform.openai.com/account/usage",
  "Rate limit": "Batas penggunaan terlampaui",
  "Jump to bottom": "Lompat ke bawah",
  "Explain": "Jelaskan",
  "Failed to get arkose token.": "Gagal mendapatkan token arkose.",
  "Please keep https://chatgpt.com open and try again. If it still doesn't work, type some characters in the input box of chatgpt web page and try again.": "Harap tetap buka https://chatgpt.com dan coba lagi. Jika masih tidak berhasil, ketik beberapa karakter di kotak masukan halaman web chatgpt dan coba lagi.",
  "Open Side Panel": "Buka Panel Samping",
  "Generating...": "Menghasilkan...",
  "moonshot token required, please login at https://kimi.com first, and then click the retry button": "diperlukan token moonshot, silakan masuk di https://kimi.com terlebih dahulu, lalu klik tombol coba lagi",
  "Hide context menu of this extension": "Sembunyikan menu konteks ekstensi ini",
  "Custom Anthropic API Url": "URL API Anthropic Kustom",
  "Anthropic API Key": "Kunci API Anthropic",
  "Cancel": "Batal",
  "Name is required": "Nama diperlukan",
  "Prompt template should include {{selection}}": "Template prompt harus mencakup {{selection}}",
  "Save": "Simpan",
  "Name": "Nama",
  "Icon": "Ikon",
  "Prompt Template": "Template Prompt",
  "Explain this: {{selection}}": "Jelaskan ini: {{selection}}",
  "New": "Baru",
  "Always display floating window, disable sidebar for all site adapters": "Selalu tampilkan jendela mengambang, nonaktifkan sidebar untuk semua adapter situs",
  "Allow ESC to close all floating windows": "Izinkan ESC untuk menutup semua jendela mengambang",
  "Export All Data": "Ekspor Semua Data",
  "Import All Data": "Impor Semua Data",
  "Keep-Alive Time": "Waktu Tetap Hidup",
  "5m": "5m",
  "30m": "30m",
  "Forever": "Selamanya",
  "You have successfully logged in for ChatGPTBox and can now return": "Anda telah berhasil masuk untuk ChatGPTBox dan sekarang dapat kembali",
  "Claude.ai is not available in your region": "Claude.ai tidak tersedia di wilayah Anda",
  "Claude.ai (Web)": "Claude.ai (Web)",
  "Kimi.Moonshot (Web)": "Kimi.Moonshot (Web)",
  "Bing (Web)": "Bing (Web)",
  "Gemini (Web)": "Gemini (Web)",
  "Type": "Jenis",
  "Mode": "Mode",
  "Custom": "Kustom",
  "OpenAI (API)": "OpenAI (API)",
  "Anthropic (API)": "Anthropic (API)",
  "Azure OpenAI (API)": "Azure OpenAI (API)",
  "OpenAI (GPT-3.5-turbo-16k)": "OpenAI (GPT-3.5-turbo-16k)",
  "OpenAI (GPT-4o, 128k)": "OpenAI (GPT-4o, 128k)",
  "OpenAI (GPT-4o mini)": "OpenAI (GPT-4o mini)",
  "OpenAI (GPT-4-Turbo 128k)": "OpenAI (GPT-4-Turbo 128k)",
  "OpenAI (GPT-4-Turbo 128k Preview)": "OpenAI (GPT-4-Turbo 128k Preview)",
  "OpenAI (GPT-4-Turbo 128k 1106 Preview)": "OpenAI (GPT-4-Turbo 128k 1106 Preview)",
  "OpenAI (GPT-4-Turbo 128k 0125 Preview)": "OpenAI (GPT-4-Turbo 128k 0125 Preview)",
  "OpenAI (GPT-5 latest)": "OpenAI (GPT-5 latest)",
  "OpenAI (GPT-5.1 latest)": "OpenAI (GPT-5.1 latest)",
  "OpenAI (GPT-4.1)": "OpenAI (GPT-4.1)",
  "OpenAI (GPT-4.1 mini)": "OpenAI (GPT-4.1 mini)",
  "OpenAI (GPT-4.1 nano)": "OpenAI (GPT-4.1 nano)",
  "Anthropic (Claude 3 Haiku)": "Anthropic (Claude 3 Haiku)",
  "Anthropic (Claude 3.5 Haiku)": "Anthropic (Claude 3.5 Haiku)",
  "Anthropic (Claude 3.7 Sonnet)": "Anthropic (Claude 3.7 Sonnet)",
  "Anthropic (Claude Opus 4)": "Anthropic (Claude Opus 4)",
  "Anthropic (Claude Opus 4.1)": "Anthropic (Claude Opus 4.1)",
  "Anthropic (Claude Opus 4.5)": "Anthropic (Claude Opus 4.5)",
  "Anthropic (Claude Opus 4.6)": "Anthropic (Claude Opus 4.6)",
  "Anthropic (Claude Sonnet 4)": "Anthropic (Claude Sonnet 4)",
  "Anthropic (Claude Sonnet 4.5)": "Anthropic (Claude Sonnet 4.5)",
  "Anthropic (Claude Haiku 4.5)": "Anthropic (Claude Haiku 4.5)",
  "OpenAI (GPT-3.5-turbo 1106)": "OpenAI (GPT-3.5-turbo 1106)",
  "OpenAI (GPT-3.5-turbo 0125)": "OpenAI (GPT-3.5-turbo 0125)",
  "OpenAI (GPT-4-8k 0613)": "OpenAI (GPT-4-8k 0613)",
  "Azure OpenAI": "Azure OpenAI",
  "OpenAI (GPT-5)": "OpenAI (GPT-5)",
  "OpenAI (GPT-5.1)": "OpenAI (GPT-5.1)",
  "OpenAI (GPT-5.2 latest)": "OpenAI (GPT-5.2 latest)",
  "OpenAI (GPT-5.2)": "OpenAI (GPT-5.2)",
  "OpenAI (GPT-5.3 latest)": "OpenAI (GPT-5.3 latest)",
  "OpenAI (GPT-5.4)": "OpenAI (GPT-5.4)",
  "OpenAI (GPT-5.4 mini)": "OpenAI (GPT-5.4 mini)",
  "OpenAI (GPT-5.4 nano)": "OpenAI (GPT-5.4 nano)",
  "Anthropic (Claude Sonnet 4.6)": "Anthropic (Claude Sonnet 4.6)"
}


================================================
FILE: src/_locales/it/main.json
================================================
{
  "General": "Generale",
  "Selection Tools": "Strumenti di selezione",
  "Sites": "Siti Web",
  "Advanced": "Avanzato",
  "Donate": "Donazione",
  "Triggers": "Trigger",
  "Theme": "Tema",
  "API Mode": "Modalità API",
  "Get": "Ottenere",
  "Preferred Language": "Lingua preferita",
  "Insert ChatGPT at the top of search results": "Inserisci ChatGPT in cima ai risultati di ricerca",
  "Lock scrollbar while answering": "Blocca la barra di scorrimento durante la risposta",
  "Current Version": "Versione corrente",
  "Latest": "Ultima",
  "Help | Changelog ": "Aiuto | Cronologia delle modifiche ",
  "Custom ChatGPT Web API Url": "URL API Web ChatGPT personalizzato",
  "Custom ChatGPT Web API Path": "Percorso API Web ChatGPT personalizzato",
  "Custom OpenAI API Url": "URL API OpenAI personalizzato",
  "Custom Site Regex": "Espressione regolare del sito personalizzata",
  "Exclusively use Custom Site Regex for website matching, ignoring built-in rules": "Usa esclusivamente l'espressione regolare del sito personalizzata per la corrispondenza dei siti Web, ignorando le regole incorporate",
  "Input Query": "Query di input",
  "Append Query": "Query di appendice",
  "Prepend Query": "Query di aggiunta in testa",
  "Wechat Pay": "Paga con Wechat",
  "Type your question here\nEnter to send, shift + enter to break line": "Digita la tua domanda qui\nInvio per inviare, shift + invio per andare a capo",
  "Type your question here\nEnter to stop generating\nShift + enter to break line": "Digita la tua domanda qui\nPremi Invio per interrompere la generazione\nShift + Invio per andare a capo",
  "Ask ChatGPT": "Chiedi a ChatGPT",
  "No Input Found": "Nessun ingresso trovato",
  "You": "Tu",
  "Collapse": "Comprimi",
  "Expand": "Espandi",
  "Stop": "Stop",
  "Continue on official website": "Continua sul sito ufficiale",
  "Error": "Errore",
  "Copy": "Copia",
  "Question": "Domanda",
  "Answer": "Risposta",
  "Waiting for response...": "In attesa di risposta...",
  "Close the Window": "Chiudi la finestra",
  "Pin the Window": "Fissa la finestra",
  "Float the Window": "Finestra flottante",
  "Save Conversation": "Salva la conversazione",
  "UNAUTHORIZED": "Non autorizzato",
  "Please login at https://chatgpt.com first": "Effettua il login su https://chatgpt.com prima",
  "Please login at https://claude.ai first, and then click the retry button": "Effettua il login su https://claude.ai prima, quindi fai clic sul pulsante Riprova",
  "Please login at https://bing.com first": "Effettua il login su https://bing.com prima",
  "Then open https://chatgpt.com/api/auth/session": "Quindi apri https://chatgpt.com/api/auth/session",
  "And refresh this page or type you question again": "Quindi fare clic sul pulsante Riprova nell'angolo in alto a destra",
  "Consider creating an api key at https://platform.openai.com/account/api-keys": "Considera la creazione di una chiave API su https://platform.openai.com/account/api-keys",
  "OpenAI Security Check Required": "Richiesta verifica di sicurezza OpenAI",
  "Please open https://chatgpt.com/api/auth/session": "Apri https://chatgpt.com/api/auth/session",
  "Please open https://chatgpt.com": "Apri https://chatgpt.com",
  "New Chat": "Nuova chat",
  "Summarize Page": "Riassumi la pagina",
  "Translate": "Traduci",
  "Translate (Bidirectional)": "Traduci (Bidirezionale)",
  "Translate (To English)": "Traduci (Verso l'inglese)",
  "Translate (To Chinese)": "Traduci (Verso il cinese)",
  "Summary": "Riassumi",
  "Polish": "Revisiona",
  "Sentiment Analysis": "Analisi dei sentimenti",
  "Divide Paragraphs": "Dividi in paragrafi",
  "Code Explain": "Spiega il codice",
  "Ask": "Chiedi",
  "Always": "Sempre",
  "Manually": "Manualmente",
  "When query ends with question mark (?)": "Quando la query termina con il punto interrogativo (?)",
  "Light": "Chiaro",
  "Dark": "Scuro",
  "Auto": "Automatico",
  "ChatGPT (Web)": "ChatGPT (Web)",
  "ChatGPT (Web, GPT-4)": "ChatGPT (Web, GPT-4)",
  "Bing (Web, GPT-4)": "Bing (Web, GPT-4)",
  "ChatGPT (GPT-3.5-turbo)": "ChatGPT (GPT-3.5-turbo)",
  "OpenAI (GPT-3.5-turbo)": "OpenAI (GPT-3.5-turbo)",
  "ChatGPT (GPT-4-8k)": "ChatGPT (GPT-4-8k)",
  "OpenAI (GPT-4-8k)": "OpenAI (GPT-4-8k)",
  "ChatGPT (GPT-4-32k)": "ChatGPT (GPT-4-32k)",
  "GPT-3.5": "GPT-3.5",
  "Custom Model": "Modello personalizzato",
  "Balanced": "Bilanciato",
  "Creative": "Creativo",
  "Precise": "Preciso",
  "Fast": "Veloce",
  "API Key": "Chiave API",
  "Model Name": "Nome del modello",
  "Custom Model API Url": "URL API del modello personalizzato",
  "Loading...": "Caricamento...",
  "Feedback": "Feedback",
  "Confirm": "Conferma",
  "Clear Conversation": "Pulisci la conversazione",
  "Retry": "Riprova",
  "Exceeded maximum context length": "Lunghezza massima del contesto superata, si prega di pulire la conversazione e riprovare",
  "Regenerate the answer after switching model": "Rigenerare la risposta dopo aver cambiato il modello",
  "Pin": "Fissa",
  "Unpin": "Sblocca",
  "Delete Conversation": "Elimina la conversazione",
  "Clear conversations": "Pulisci le conversazioni",
  "Settings": "Impostazioni",
  "Feature Pages": "Pagine delle funzionalità",
  "Keyboard Shortcuts": "Scorciatoie da tastiera",
  "Open Conversation Page": "Apri la pagina della conversazione",
  "Open Conversation Window": "Apri la finestra di conversazione",
  "Store to Independent Conversation Page": "Conserva sulla pagina della conversazione indipendente",
  "Keep Conversation Window in Background": "Mantieni la finestra di conversazione in background, per aprirla in qualsiasi programma tramite scorciatoie",
  "Max Response Token Length": "Lunghezza massima del token di risposta",
  "Max Conversation Length": "Lunghezza massima della conversazione",
  "Always pin the floating window": "Fissare sempre la finestra flottante",
  "Export": "Esporta",
  "Always Create New Conversation Window": "Crea sempre una nuova finestra di conversazione",
  "Please keep this tab open. You can now use the web mode of ChatGPTBox": "Per favore, mantieni questa scheda aperta. Ora puoi utilizzare la modalità web di ChatGPTBox",
  "Go Back": "Torna indietro",
  "Pin Tab": "Fissa scheda",
  "Modules": "Moduli",
  "API Params": "Parametri API",
  "API Url": "URL API",
  "Others": "Altri",
  "API Modes": "Modalità API",
  "Disable web mode history for better privacy protection, but it will result in unavailable conversations after a period of time": "Disabilita la cronologia della modalità web per una migliore protezione della privacy, ma ciò comporterà conversazioni non disponibili dopo un certo periodo di tempo",
  "Display selection tools next to input box to avoid blocking": "Mostra gli strumenti di selezione accanto alla casella di input per evitare il blocco",
  "Close All Chats In This Page": "Chiudi tutte le chat in questa pagina",
  "When Icon Clicked": "Quando viene cliccata l'icona",
  "Open Settings": "Apri impostazioni",
  "Focus to input box after answering": "Focus sulla casella di input dopo aver risposto",
  "Bing CaptchaChallenge": "Sfida Captcha di Bing: è necessario superare la verifica di Bing. Apri https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx e invia un messaggio.",
  "Exceeded quota": "Limite superato o scaduto, controlla questo link: https://platform.openai.com/account/usage",
  "Rate limit": "Limite di frequenza delle richieste raggiunto",
  "Jump to bottom": "Salta in fondo",
  "Explain": "Spiega",
  "Failed to get arkose token.": "Impossibile ottenere il token arkose",
  "Please keep https://chatgpt.com open and try again. If it still doesn't work, type some characters in the input box of chatgpt web page and try again.": "Per favore, mantieni aperto https://chatgpt.com e riprova. Se ancora non funziona, digita alcuni caratteri nella casella di input della pagina web di chatgpt e riprova.",
  "Open Side Panel": "Apri il pannello laterale",
  "Generating...": "Generazione...",
  "moonshot token required, please login at https://kimi.com first, and then click the retry button": "richiesto token moonshot, effettua il login su https://kimi.com prima, quindi fai clic sul pulsante Riprova",
  "Hide context menu of this extension": "Nascondi il menu contestuale di questa estensione",
  "Custom Anthropic API Url": "URL API Anthropic personalizzato",
  "Anthropic API Key": "Chiave API Anthropic",
  "Cancel": "Annulla",
  "Name is required": "Il nome è obbligatorio",
  "Prompt template should include {{selection}}": "Il modello di prompt dovrebbe includere {{selection}}",
  "Save": "Salva",
  "Name": "Nome",
  "Icon": "Icona",
  "Prompt Template": "Modello di prompt",
  "Explain this: {{selection}}": "Spiega questo: {{selection}}",
  "New": "Nuovo",
  "Always display floating window, disable sidebar for all site adapters": "Mostra sempre la finestra flottante, disabilita la barra laterale per tutti gli adattatori del sito",
  "Allow ESC to close all floating windows": "Consenti ESC per chiudere tutte le finestre flottanti",
  "Export All Data": "Esporta tutti i dati",
  "Import All Data": "Importa tutti i dati",
  "Keep-Alive Time": "Tempo di mantenimento",
  "5m": "5m",
  "30m": "30m",
  "Forever": "Per sempre",
  "You have successfully logged in for ChatGPTBox and can now return": "Ti sei autenticato con successo per ChatGPTBox e ora puoi tornare",
  "Claude.ai is not available in your region": "Claude.ai non è disponibile nella tua regione",
  "Claude.ai (Web)": "Claude.ai (Web)",
  "Kimi.Moonshot (Web)": "Kimi.Moonshot (Web)",
  "Bing (Web)": "Bing (Web)",
  "Gemini (Web)": "Gemini (Web)",
  "Type": "Tipo",
  "Mode": "Modalità",
  "Custom": "Personalizzato",
  "OpenAI (API)": "OpenAI (API)",
  "Anthropic (API)": "Anthropic (API)",
  "Azure OpenAI (API)": "Azure OpenAI (API)",
  "OpenAI (GPT-3.5-turbo-16k)": "OpenAI (GPT-3.5-turbo-16k)",
  "OpenAI (GPT-4o, 128k)": "OpenAI (GPT-4o, 128k)",
  "OpenAI (GPT-4o mini)": "OpenAI (GPT-4o mini)",
  "OpenAI (GPT-4-Turbo 128k)": "OpenAI (GPT-4-Turbo 128k)",
  "OpenAI (GPT-4-Turbo 128k Preview)": "OpenAI (GPT-4-Turbo 128k Preview)",
  "OpenAI (GPT-4-Turbo 128k 1106 Preview)": "OpenAI (GPT-4-Turbo 128k 1106 Preview)",
  "OpenAI (GPT-4-Turbo 128k 0125 Preview)": "OpenAI (GPT-4-Turbo 128k 0125 Preview)",
  "OpenAI (GPT-5 latest)": "OpenAI (GPT-5 latest)",
  "OpenAI (GPT-5.1 latest)": "OpenAI (GPT-5.1 latest)",
  "OpenAI (GPT-4.1)": "OpenAI (GPT-4.1)",
  "OpenAI (GPT-4.1 mini)": "OpenAI (GPT-4.1 mini)",
  "OpenAI (GPT-4.1 nano)": "OpenAI (GPT-4.1 nano)",
  "Anthropic (Claude 3 Haiku)": "Anthropic (Claude 3 Haiku)",
  "Anthropic (Claude 3.5 Haiku)": "Anthropic (Claude 3.5 Haiku)",
  "Anthropic (Claude 3.7 Sonnet)": "Anthropic (Claude 3.7 Sonnet)",
  "Anthropic (Claude Opus 4)": "Anthropic (Claude Opus 4)",
  "Anthropic (Claude Opus 4.1)": "Anthropic (Claude Opus 4.1)",
  "Anthropic (Claude Opus 4.5)": "Anthropic (Claude Opus 4.5)",
  "Anthropic (Claude Opus 4.6)": "Anthropic (Claude Opus 4.6)",
  "Anthropic (Claude Sonnet 4)": "Anthropic (Claude Sonnet 4)",
  "Anthropic (Claude Sonnet 4.5)": "Anthropic (Claude Sonnet 4.5)",
  "Anthropic (Claude Haiku 4.5)": "Anthropic (Claude Haiku 4.5)",
  "OpenAI (GPT-3.5-turbo 1106)": "OpenAI (GPT-3.5-turbo 1106)",
  "OpenAI (GPT-3.5-turbo 0125)": "OpenAI (GPT-3.5-turbo 0125)",
  "OpenAI (GPT-4-8k 0613)": "OpenAI (GPT-4-8k 0613)",
  "Azure OpenAI": "Azure OpenAI",
  "OpenAI (GPT-5)": "OpenAI (GPT-5)",
  "OpenAI (GPT-5.1)": "OpenAI (GPT-5.1)",
  "OpenAI (GPT-5.2 latest)": "OpenAI (GPT-5.2 latest)",
  "OpenAI (GPT-5.2)": "OpenAI (GPT-5.2)",
  "OpenAI (GPT-5.3 latest)": "OpenAI (GPT-5.3 latest)",
  "OpenAI (GPT-5.4)": "OpenAI (GPT-5.4)",
  "OpenAI (GPT-5.4 mini)": "OpenAI (GPT-5.4 mini)",
  "OpenAI (GPT-5.4 nano)": "OpenAI (GPT-5.4 nano)",
  "Anthropic (Claude Sonnet 4.6)": "Anthropic (Claude Sonnet 4.6)"
}


================================================
FILE: src/_locales/ja/main.json
================================================
{
  "General": "一般",
  "Selection Tools": "選択ツール",
  "Sites": "サイト適応",
  "Advanced": "高度な",
  "Donate": "寄付",
  "Triggers": "トリガー",
  "Theme": "テーマ",
  "API Mode": "APIモード",
  "Get": "取得",
  "Preferred Language": "言語設定",
  "Insert ChatGPT at the top of search results": "検索結果のトップにチャットGPTを挿入",
  "Lock scrollbar while answering": "回答中にスクロールバーをロック",
  "Current Version": "現在のバージョン",
  "Latest": "最新版",
  "Help | Changelog ": "ヘルプ | チェンジログ ",
  "Custom ChatGPT Web API Url": "カスタムChatGPT Web APIのURL",
  "Custom ChatGPT Web API Path": "カスタムChatGPT Web APIのパス",
  "Custom OpenAI API Url": "カスタムOpenAI APIのURL",
  "Custom Site Regex": "カスタムサイトの正規表現",
  "Exclusively use Custom Site Regex for website matching, ignoring built-in rules": "内蔵ルールを無視して、カスタムサイト用の正規表現のみを使用",
  "Input Query": "入力クエリ",
  "Append Query": "末尾に追加するクエリ",
  "Prepend Query": "先頭に挿入するクエリ",
  "Wechat Pay": "Wechatペイ",
  "Type your question here\nEnter to send, shift + enter to break line": "ここに質問を入力してください\nEnterで送信、shift+Enterで改行",
  "Type your question here\nEnter to stop generating\nShift + enter to break line": "ここに質問を入力してください\nEnterで生成を停止、Shift + Enterで改行",
  "Ask ChatGPT": "ChatGPTに質問する",
  "No Input Found": "入力が見つかりません",
  "You": "あなた",
  "Collapse": "折りたたむ",
  "Expand": "展開",
  "Stop": "停止",
  "Continue on official website": "公式サイトで続ける",
  "Error": "エラー",
  "Copy": "コピー",
  "Question": "質問",
  "Answer": "回答",
  "Waiting for response...": "回答を待機中...",
  "Close the Window": "ウィンドウを閉じる",
  "Pin the Window": "ウィンドウをピン留め",
  "Float the Window": "ウィンドウをフロート/分割表示",
  "Save Conversation": "会話を保存",
  "UNAUTHORIZED": "認証されていません",
  "Please login at https://chatgpt.com first": "最初に https://chatgpt.com にログインしてください",
  "Please login at https://claude.ai first, and then click the retry button": "最初に https://claude.ai にログインしてから、再試行ボタンをクリックしてください",
  "Please login at https://bing.com first": "最初に https://bing.com にログインしてください",
  "Then open https://chatgpt.com/api/auth/session": "次に https://chatgpt.com/api/auth/session にアクセス",
  "And refresh this page or type you question again": "次に、右上の「再試行」ボタンをクリックします",
  "Consider creating an api key at https://platform.openai.com/account/api-keys": "https://platform.openai.com/account/api-keys でAPIキーを作成してください",
  "OpenAI Security Check Required": "OpenAIのセキュリティチェックが必要です",
  "Please open https://chatgpt.com/api/auth/session": "https://chatgpt.com/api/auth/session にアクセスしてください",
  "Please open https://chatgpt.com": "https://chatgpt.com にアクセスしてください",
  "New Chat": "新しいチャット",
  "Summarize Page": "ページをまとめる",
  "Translate": "翻訳",
  "Translate (Bidirectional)": "双向翻訳",
  "Translate (To English)": "英語に翻訳",
  "Translate (To Chinese)": "中国語に翻訳",
  "Summary": "サマリー",
  "Polish": "ポリッシュ",
  "Sentiment Analysis": "感情分析",
  "Divide Paragraphs": "パラグラフ分割",
  "Code Explain": "コードの解説",
  "Ask": "質問",
  "Always": "常時",
  "Manually": "手動で",
  "When query ends with question mark (?)": "クエリが「?」で終わる場合",
  "Light": "ライト",
  "Dark": "ダーク",
  "Auto": "オート",
  "ChatGPT (Web)": "ChatGPT (Web)",
  "ChatGPT (Web, GPT-4)": "ChatGPT (Web, GPT-4)",
  "Bing (Web, GPT-4)": "Bing (Web, GPT-4)",
  "ChatGPT (GPT-3.5-turbo)": "ChatGPT (GPT-3.5-turbo)",
  "OpenAI (GPT-3.5-turbo)": "OpenAI (GPT-3.5-turbo)",
  "ChatGPT (GPT-4-8k)": "ChatGPT (GPT-4-8k)",
  "OpenAI (GPT-4-8k)": "OpenAI (GPT-4-8k)",
  "ChatGPT (GPT-4-32k)": "ChatGPT (GPT-4-32k)",
  "GPT-3.5": "GPT-3.5",
  "Custom Model": "カスタムモデル",
  "Balanced": "バランスの取れた",
  "Creative": "創造的な",
  "Precise": "正確な",
  "Fast": "高速",
  "API Key": "APIキー",
  "Model Name": "モデル名",
  "Custom Model API Url": "カスタムモデルのAPI URL",
  "Loading...": "読み込み中...",
  "Feedback": "フィードバック",
  "Confirm": "確認",
  "Clear Conversation": "会話をクリア",
  "Retry": "再試行",
  "Exceeded maximum context length": "最大コンテキスト長を超えました。会話をクリアして再試行してください",
  "Regenerate the answer after switching model": "モデルを切り替えた後に回答を再生成",
  "Pin": "ピン留め",
  "Unpin": "ピン留め解除",
  "Delete Conversation": "会話を削除",
  "Clear conversations": "会話をクリア",
  "Settings": "設定",
  "Feature Pages": "機能ページ",
  "Keyboard Shortcuts": "キーボードショートカット",
  "Open Conversation Page": "会話ページを開く",
  "Open Conversation Window": "会話ウィンドウを開く",
  "Store to Independent Conversation Page": "独立した会話ページに保存",
  "Keep Conversation Window in Background": "会話ウィンドウをバックグラウンドで保持して、任意のプログラムでショートカットキーを使用できます",
  "Max Response Token Length": "最大応答トークン長",
  "Max Conversation Length": "最大会話長",
  "Always pin the floating window": "常にフローティングウィンドウをピン留め",
  "Export": "エクスポート",
  "Always Create New Conversation Window": "常に新しい会話ウィンドウを作成",
  "Please keep this tab open. You can now use the web mode of ChatGPTBox": "このタブを開いたままにしてください。これでChatGPTBoxのWebモードを使用できます",
  "Go Back": "戻る",
  "Pin Tab": "タブをピン留め",
  "Modules": "モジュール",
  "API Params": "APIパラメータ",
  "API Url": "API URL",
  "Others": "その他",
  "API Modes": "APIモード",
  "Disable web mode history for better privacy protection, but it will result in unavailable conversations after a period of time": "プライバシー保護の向上のためにWebモードの履歴を無効にしますが、一定期間後に会話が利用できなくなります",
  "Display selection tools next to input box to avoid blocking": "ブロッキングを回避するために入力ボックスの隣に選択ツールを表示",
  "Close All Chats In This Page": "このページのすべてのチャットを閉じる",
  "When Icon Clicked": "アイコンがクリックされたとき",
  "Open Settings": "設定を開く",
  "Focus to input box after answering": "回答後に入力ボックスにフォーカス",
  "Bing CaptchaChallenge": "Bing CaptchaChallenge:https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx を開いてメッセージを送信する必要があります",
  "Exceeded quota": "クォータを超過しました。https://platform.openai.com/account/usage で残高を確認してください",
  "Rate limit": "レート制限",
  "Jump to bottom": "最下部にジャンプ",
  "Explain": "説明",
  "Failed to get arkose token.": "arkoseトークンの取得に失敗しました。",
  "Please keep https://chatgpt.com open and try again. If it still doesn't work, type some characters in the input box of chatgpt web page and try again.": "https://chatgpt.com を開いたままにして、もう一度試してください。それでもうまくいかない場合は、chatgpt webページの入力ボックスにいくつかの文字を入力してからもう一度試してください。",
  "Open Side Panel": "サイドパネルを開く",
  "Generating...": "生成中...",
  "moonshot token required, please login at https://kimi.com first, and then click the retry button": "moonshotトークンが必要です。最初に https://kimi.com にログインしてから、再試行ボタンをクリックしてください",
  "Hide context menu of this extension": "この拡張機能のコンテキストメニューを非表示",
  "Custom Anthropic API Url": "カスタムAnthropic APIのURL",
  "Anthropic API Key": "Anthropic API キー",
  "Cancel": "キャンセル",
  "Name is required": "名前は必須です",
  "Prompt template should include {{selection}}": "プロンプトテンプレートには {{selection}} を含める必要があります",
  "Save": "保存",
  "Name": "名前",
  "Icon": "アイコン",
  "Prompt Template": "プロンプトテンプレート",
  "Explain this: {{selection}}": "これを説明する: {{selection}}",
  "New": "新規",
  "Always display floating window, disable sidebar for all site adapters": "常にフローティングウィンドウを表示し、すべてのサイトアダプターでサイドバーを無効にします",
  "Allow ESC to close all floating windows": "ESCキーですべてのフローティングウィンドウを閉じる",
  "Export All Data": "すべてのデータをエクスポート",
  "Import All Data": "すべてのデータをインポート",
  "Keep-Alive Time": "Keep-Alive時間",
  "5m": "5分",
  "30m": "30分",
  "Forever": "永久",
  "You have successfully logged in for ChatGPTBox and can now return": "ChatGPTBoxに正常にログインしました。これで戻ることができます",
  "Claude.ai is not available in your region": "Claude.ai はあなたの地域では利用できません",
  "Claude.ai (Web)": "Claude.ai (Web)",
  "Kimi.Moonshot (Web)": "Kimi.Moonshot (Web)",
  "Bing (Web)": "Bing (Web)",
  "Gemini (Web)": "Gemini (Web)",
  "Type": "タイプ",
  "Mode": "モード",
  "Custom": "カスタム",
  "OpenAI (API)": "OpenAI (API)",
  "Anthropic (API)": "Anthropic (API)",
  "Azure OpenAI (API)": "Azure OpenAI (API)",
  "OpenAI (GPT-3.5-turbo-16k)": "OpenAI (GPT-3.5-turbo-16k)",
  "OpenAI (GPT-4o, 128k)": "OpenAI (GPT-4o, 128k)",
  "OpenAI (GPT-4o mini)": "OpenAI (GPT-4o mini)",
  "OpenAI (GPT-4-Turbo 128k)": "OpenAI (GPT-4-Turbo 128k)",
  "OpenAI (GPT-4-Turbo 128k Preview)": "OpenAI (GPT-4-Turbo 128k Preview)",
  "OpenAI (GPT-4-Turbo 128k 1106 Preview)": "OpenAI (GPT-4-Turbo 128k 1106 Preview)",
  "OpenAI (GPT-4-Turbo 128k 0125 Preview)": "OpenAI (GPT-4-Turbo 128k 0125 Preview)",
  "OpenAI (GPT-5 latest)": "OpenAI (GPT-5 latest)",
  "OpenAI (GPT-5.1 latest)": "OpenAI (GPT-5.1 latest)",
  "OpenAI (GPT-4.1)": "OpenAI (GPT-4.1)",
  "OpenAI (GPT-4.1 mini)": "OpenAI (GPT-4.1 mini)",
  "OpenAI (GPT-4.1 nano)": "OpenAI (GPT-4.1 nano)",
  "Anthropic (Claude 3 Haiku)": "Anthropic (Claude 3 Haiku)",
  "Anthropic (Claude 3.5 Haiku)": "Anthropic (Claude 3.5 Haiku)",
  "Anthropic (Claude 3.7 Sonnet)": "Anthropic (Claude 3.7 Sonnet)",
  "Anthropic (Claude Opus 4)": "Anthropic (Claude Opus 4)",
  "Anthropic (Claude Opus 4.1)": "Anthropic (Claude Opus 4.1)",
  "Anthropic (Claude Opus 4.5)": "Anthropic (Claude Opus 4.5)",
  "Anthropic (Claude Opus 4.6)": "Anthropic (Claude Opus 4.6)",
  "Anthropic (Claude Sonnet 4)": "Anthropic (Claude Sonnet 4)",
  "Anthropic (Claude Sonnet 4.5)": "Anthropic (Claude Sonnet 4.5)",
  "Anthropic (Claude Haiku 4.5)": "Anthropic (Claude Haiku 4.5)",
  "OpenAI (GPT-3.5-turbo 1106)": "OpenAI (GPT-3.5-turbo 1106)",
  "OpenAI (GPT-3.5-turbo 0125)": "OpenAI (GPT-3.5-turbo 0125)",
  "OpenAI (GPT-4-8k 0613)": "OpenAI (GPT-4-8k 0613)",
  "Azure OpenAI": "Azure OpenAI",
  "OpenAI (GPT-5)": "OpenAI (GPT-5)",
  "OpenAI (GPT-5.1)": "OpenAI (GPT-5.1)",
  "OpenAI (GPT-5.2 latest)": "OpenAI (GPT-5.2 latest)",
  "OpenAI (GPT-5.2)": "OpenAI (GPT-5.2)",
  "OpenAI (GPT-5.3 latest)": "OpenAI (GPT-5.3 latest)",
  "OpenAI (GPT-5.4)": "OpenAI (GPT-5.4)",
  "OpenAI (GPT-5.4 mini)": "OpenAI (GPT-5.4 mini)",
  "OpenAI (GPT-5.4 nano)": "OpenAI (GPT-5.4 nano)",
  "Anthropic (Claude Sonnet 4.6)": "Anthropic (Claude Sonnet 4.6)"
}


================================================
FILE: src/_locales/ko/main.json
================================================
{
  "General": "일반",
  "Selection Tools": "선택 도구",
  "Sites": "사이트",
  "Advanced": "고급",
  "Donate": "기부",
  "Triggers": "트리거",
  "Theme": "테마",
  "API Mode": "API 모드",
  "Get": "받다",
  "Preferred Language": "선호하는 언어",
  "Insert ChatGPT at the top of search results": "검색 결과 상단에 ChatGPT 삽입",
  "Lock scrollbar while answering": "답변 중 스크롤바 잠금",
  "Current Version": "현재 버전",
  "Latest": "최신",
  "Help | Changelog ": "도움말 | 변경 로그 ",
  "Custom ChatGPT Web API Url": "사용자 정의 ChatGPT 웹 API URL",
  "Custom ChatGPT Web API Path": "사용자 정의 ChatGPT 웹 API 경로",
  "Custom OpenAI API Url": "사용자 정의 OpenAI API URL",
  "Custom Site Regex": "사용자 정의 사이트 Regex",
  "Exclusively use Custom Site Regex for website matching, ignoring built-in rules": "사이트 일치에 독점적으로 사용자 정의 사이트 Regex를 사용하며, 내장 규칙을 무시합니다.",
  "Input Query": "입력 쿼리 선택기",
  "Append Query": "끝에 추가할 쿼리 선택기",
  "Prepend Query": "앞에 추가할 쿼리 선택기",
  "Wechat Pay": "위챗 페이",
  "Type your question here\nEnter to send, shift + enter to break line": "여기에 질문을 입력하세요. \n 보내려면 엔터, 줄바꿈을 하려면 shift + enter를 누르세요.",
  "Type your question here\nEnter to stop generating\nShift + enter to break line": "여기에 질문을 입력하세요.\nEnter로 생성을 중지하려면 \nShift + Enter로 줄을 바꾸세요.",
  "Ask ChatGPT": "ChatGPT에게 물어보세요.",
  "No Input Found": "입력 없음",
  "You": "당신",
  "Collapse": "축소",
  "Expand": "확장",
  "Stop": "중지",
  "Continue on official website": "공식 웹사이트에서 계속하기",
  "Error": "오류",
  "Copy": "복사",
  "Question": "질문",
  "Answer": "대답",
  "Waiting for response...": "응답 대기 중...",
  "Close the Window": "창 닫기",
  "Pin the Window": "창 고정",
  "Float the Window": "창 띄우기",
  "Save Conversation": "대화 저장",
  "UNAUTHORIZED": "인증되지 않음",
  "Please login at https://chatgpt.com first": "https://chatgpt.com 에서 로그인하세요.",
  "Please login at https://claude.ai first, and then click the retry button": "https://claude.ai 에서 로그인한 다음 재시도 버튼을 클릭하세요.",
  "Please login at https://bing.com first": "https://bing.com 에서 로그인하세요.",
  "Then open https://chatgpt.com/api/auth/session": "그런 다음 https://chatgpt.com/api/auth/session 을 열거나 다시 질문을 입력하세요.",
  "And refresh this page or type you question again": "그런 다음 오른쪽 상단의 재시도 버튼을 클릭합니다.",
  "Consider creating an api key at https://platform.openai.com/account/api-keys": "https://platform.openai.com/account/api-keys 에서 API 키를 생성하는 것을 고려하세요.",
  "OpenAI Security Check Required": "OpenAI 보안 검사 필요",
  "Please open https://chatgpt.com/api/auth/session": "https://chatgpt.com/api/auth/session 을 열어주세요.",
  "Please open https://chatgpt.com": "https://chatgpt.com 을 열어주세요.",
  "New Chat": "새로운 대화",
  "Summarize Page": "페이지 요약",
  "Translate": "번역",
  "Translate (Bidirectional)": "양방향 번역",
  "Translate (To English)": "영어로 번역",
  "Translate (To Chinese)": "중국어로 번역",
  "Summary": "요약",
  "Polish": "마무리 작업",
  "Sentiment Analysis": "감성 분석",
  "Divide Paragraphs": "문단 나누기",
  "Code Explain": "코드 설명",
  "Ask": "문의하기",
  "Always": "항상",
  "Manually": "수동으로",
  "When query ends with question mark (?)": "쿼리가 물음표로 끝날 때",
  "Light": "라이트",
  "Dark": "다크",
  "Auto": "자동",
  "ChatGPT (Web)": "ChatGPT (Web)",
  "ChatGPT (Web, GPT-4)": "ChatGPT (Web, GPT-4)",
  "Bing (Web, GPT-4)": "Bing (Web, GPT-4)",
  "ChatGPT (GPT-3.5-turbo)": "ChatGPT (GPT-3.5-turbo)",
  "OpenAI (GPT-3.5-turbo)": "OpenAI (GPT-3.5-turbo)",
  "ChatGPT (GPT-4-8k)": "ChatGPT (GPT-4-8k)",
  "OpenAI (GPT-4-8k)": "OpenAI (GPT-4-8k)",
  "ChatGPT (GPT-4-32k)": "ChatGPT (GPT-4-32k)",
  "GPT-3.5": "GPT-3.5",
  "Custom Model": "사용자 정의 모델",
  "Balanced": "균형 잡힌",
  "Creative": "창의적인",
  "Precise": "정확한",
  "Fast": "빠른",
  "API Key": "API 키",
  "Model Name": "모델 이름",
  "Custom Model API Url": "사용자 정의 모델 API URL",
  "Loading...": "로딩 중...",
  "Feedback": "피드백",
  "Confirm": "확인",
  "Clear Conversation": "대화 내용 지우기",
  "Retry": "재시도",
  "Exceeded maximum context length": "최대 컨텍스트 길이를 초과하였습니다. 대화 내용을 지우고 다시 시도해주세요.",
  "Regenerate the answer after switching model": "모델 전환 후 대답 다시 생성",
  "Pin": "고정",
  "Unpin": "고정 해제",
  "Delete Conversation": "대화 삭제",
  "Clear conversations": "대화 기록 지우기",
  "Settings": "설정",
  "Feature Pages": "기능 페이지",
  "Keyboard Shortcuts": "키보드 단축키 설정",
  "Open Conversation Page": "대화 페이지 열기",
  "Open Conversation Window": "대화 창 열기",
  "Store to Independent Conversation Page": "독립적인 대화 페이지에 저장",
  "Keep Conversation Window in Background": "대화 창을 백그라운드로 유지하여 어떤 프로그램에서도 단축키로 호출할 수 있도록 합니다",
  "Max Response Token Length": "최대 응답 토큰 길이",
  "Max Conversation Length": "최대 대화 길이",
  "Always pin the floating window": "항상 떠다니는 창 고정",
  "Export": "내보내기",
  "Always Create New Conversation Window": "항상 새 대화 창 만들기",
  "Please keep this tab open. You can now use the web mode of ChatGPTBox": "이 탭을 열어두세요. 이제 ChatGPTBox의 웹 모드를 사용할 수 있습니다.",
  "Go Back": "뒤로 가기",
  "Pin Tab": "탭 고정",
  "Modules": "모듈",
  "API Params": "API 매개변수",
  "API Url": "API 주소",
  "Others": "기타",
  "API Modes": "API 모드",
  "Disable web mode history for better privacy protection, but it will result in unavailable conversations after a period of time": "개인 정보 보호를 위해 웹 모드 기록을 비활성화하지만 일정 시간 이후에 대화를 사용할 수 없게 됩니다.",
  "Display selection tools next to input box to avoid blocking": "차단을 피하려면 입력 상자 옆에 선택 도구를 표시",
  "Close All Chats In This Page": "이 페이지의 모든 채팅 닫기",
  "When Icon Clicked": "아이콘이 클릭되었을 때",
  "Open Settings": "설정 열기",
  "Focus to input box after answering": "답변 후 입력 상자에 초점 맞추기",
  "Bing CaptchaChallenge": "Bing CaptchaChallenge: https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx 링크를 열고 메시지를 보내야 합니다.",
  "Exceeded quota": "할당량 초과: https://platform.openai.com/account/usage 링크에서 잔액을 확인하세요.",
  "Rate limit": "요청 비율 제한",
  "Jump to bottom": "아래로 이동",
  "Explain": "설명",
  "Failed to get arkose token.": "arkose 토큰을 가져오지 못했습니다.",
  "Please keep https://chatgpt.com open and try again. If it still doesn't work, type some characters in the input box of chatgpt web page and try again.": "https://chatgpt.com 을 열어두고 다시 시도하세요. 여전히 작동하지 않으면 chatgpt 웹 페이지의 입력 상자에 몇 가지 문자를 입력한 다음 다시 시도하세요.",
  "Open Side Panel": "사이드 패널 열기",
  "Generating...": "생성 중...",
  "moonshot token required, please login at https://kimi.com first, and then click the retry button": "moonshot 토큰이 필요합니다. https://kimi.com 에서 로그인한 다음 재시도 버튼을 클릭하세요.",
  "Hide context menu of this extension": "이 확장 프로그램의 컨텍스트 메뉴 숨기기",
  "Custom Anthropic API Url": "사용자 정의 Anthropic API URL",
  "Anthropic API Key": "Anthropic API 키",
  "Cancel": "취소",
  "Name is required": "이름은 필수입니다",
  "Prompt template should include {{selection}}": "프롬프트 템플릿에는 {{selection}} 이 포함되어야 합니다",
  "Save": "저장",
  "Name": "이름",
  "Icon": "아이콘",
  "Prompt Template": "프롬프트 템플릿",
  "Explain this: {{selection}}": "이것을 설명하세요: {{selection}}",
  "New": "새로 만들기",
  "Always display floating window, disable sidebar for all site adapters": "항상 떠다니는 창을 표시하고 모든 사이트 어댑터의 사이드바를 비활성화합니다",
  "Allow ESC to close all floating windows": "ESC를 눌러 모든 떠다니는 창을 닫도록 허용",
  "Export All Data": "모든 데이터 내보내기",
  "Import All Data": "모든 데이터 가져오기",
  "Keep-Alive Time": "Keep-Alive 시간",
  "5m": "5분",
  "30m": "30분",
  "Forever": "영원히",
  "You have successfully logged in for ChatGPTBox and can now return": "ChatGPTBox에 성공적으로 로그인하였으며 이제 돌아갈 수 있습니다",
  "Claude.ai is not available in your region": "Claude.ai는 귀하의 지역에
Download .txt
gitextract_4t6jkhck/

├── .eslintrc.json
├── .gitattributes
├── .github/
│   ├── CONTRIBUTING.md
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report---问题报告.md
│   │   └── feature-request---新功能请求.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── pr-tests.yml
│       ├── pre-release-build.yml
│       ├── scripts/
│       │   ├── update-coverage-badge.mjs
│       │   └── verify-search-engine-configs.mjs
│       ├── tagged-release.yml
│       └── verify-configs.yml
├── .gitignore
├── .nvmrc
├── .prettierignore
├── .prettierrc
├── AGENTS.md
├── CURRENT_CHANGE.md
├── LICENSE
├── README.md
├── README_IN.md
├── README_JA.md
├── README_TR.md
├── README_ZH.md
├── badges/
│   └── coverage.json
├── build.mjs
├── package.json
├── safari/
│   ├── appdmg.json
│   ├── build.sh
│   ├── export-options.plist
│   ├── project.patch
│   ├── project.pre.patch
│   └── project_developer.patch
├── src/
│   ├── _locales/
│   │   ├── de/
│   │   │   └── main.json
│   │   ├── en/
│   │   │   └── main.json
│   │   ├── es/
│   │   │   └── main.json
│   │   ├── fr/
│   │   │   └── main.json
│   │   ├── i18n-react.mjs
│   │   ├── i18n.mjs
│   │   ├── in/
│   │   │   └── main.json
│   │   ├── it/
│   │   │   └── main.json
│   │   ├── ja/
│   │   │   └── main.json
│   │   ├── ko/
│   │   │   └── main.json
│   │   ├── pt/
│   │   │   └── main.json
│   │   ├── resources.mjs
│   │   ├── ru/
│   │   │   └── main.json
│   │   ├── tr/
│   │   │   └── main.json
│   │   ├── zh-hans/
│   │   │   └── main.json
│   │   └── zh-hant/
│   │       └── main.json
│   ├── background/
│   │   ├── commands.mjs
│   │   ├── index.mjs
│   │   ├── menus.mjs
│   │   └── redact.mjs
│   ├── components/
│   │   ├── ConfirmButton/
│   │   │   └── index.jsx
│   │   ├── ConversationCard/
│   │   │   └── index.jsx
│   │   ├── ConversationItem/
│   │   │   └── index.jsx
│   │   ├── CopyButton/
│   │   │   └── index.jsx
│   │   ├── DecisionCard/
│   │   │   └── index.jsx
│   │   ├── DeleteButton/
│   │   │   └── index.jsx
│   │   ├── FeedbackForChatGPTWeb/
│   │   │   └── index.jsx
│   │   ├── FloatingToolbar/
│   │   │   └── index.jsx
│   │   ├── InputBox/
│   │   │   └── index.jsx
│   │   ├── MarkdownRender/
│   │   │   ├── Hyperlink.jsx
│   │   │   ├── Pre.jsx
│   │   │   ├── markdown-without-katex.jsx
│   │   │   └── markdown.jsx
│   │   ├── ReadButton/
│   │   │   └── index.jsx
│   │   ├── WebJumpBackNotification/
│   │   │   └── index.jsx
│   │   └── index.mjs
│   ├── config/
│   │   ├── index.mjs
│   │   └── language.mjs
│   ├── content-script/
│   │   ├── index.jsx
│   │   ├── menu-tools/
│   │   │   └── index.mjs
│   │   ├── selection-tools/
│   │   │   └── index.mjs
│   │   ├── site-adapters/
│   │   │   ├── arxiv/
│   │   │   │   └── index.mjs
│   │   │   ├── baidu/
│   │   │   │   └── index.mjs
│   │   │   ├── bilibili/
│   │   │   │   └── index.mjs
│   │   │   ├── brave/
│   │   │   │   └── index.mjs
│   │   │   ├── duckduckgo/
│   │   │   │   └── index.mjs
│   │   │   ├── followin/
│   │   │   │   └── index.mjs
│   │   │   ├── github/
│   │   │   │   └── index.mjs
│   │   │   ├── gitlab/
│   │   │   │   └── index.mjs
│   │   │   ├── index.mjs
│   │   │   ├── juejin/
│   │   │   │   └── index.mjs
│   │   │   ├── quora/
│   │   │   │   └── index.mjs
│   │   │   ├── reddit/
│   │   │   │   └── index.mjs
│   │   │   ├── stackoverflow/
│   │   │   │   └── index.mjs
│   │   │   ├── weixin/
│   │   │   │   └── index.mjs
│   │   │   ├── youtube/
│   │   │   │   └── index.mjs
│   │   │   └── zhihu/
│   │   │       └── index.mjs
│   │   └── styles.scss
│   ├── fonts/
│   │   └── styles.css
│   ├── hooks/
│   │   ├── use-clamp-window-size.mjs
│   │   ├── use-config.mjs
│   │   ├── use-theme.mjs
│   │   ├── use-window-size.mjs
│   │   └── use-window-theme.mjs
│   ├── manifest.json
│   ├── manifest.v2.json
│   ├── pages/
│   │   ├── IndependentPanel/
│   │   │   ├── App.jsx
│   │   │   ├── index.html
│   │   │   ├── index.jsx
│   │   │   └── styles.scss
│   │   └── styles.scss
│   ├── popup/
│   │   ├── Popup.jsx
│   │   ├── index.html
│   │   ├── index.jsx
│   │   ├── sections/
│   │   │   ├── AdvancedPart.jsx
│   │   │   ├── ApiModes.jsx
│   │   │   ├── FeaturePages.jsx
│   │   │   ├── GeneralPart.jsx
│   │   │   ├── ModulesPart.jsx
│   │   │   ├── SelectionTools.jsx
│   │   │   ├── SiteAdapters.jsx
│   │   │   └── import-data-cleanup.mjs
│   │   └── styles.scss
│   ├── rules.json
│   ├── services/
│   │   ├── apis/
│   │   │   ├── aiml-api.mjs
│   │   │   ├── azure-openai-api.mjs
│   │   │   ├── bard-web.mjs
│   │   │   ├── bing-web.mjs
│   │   │   ├── chatglm-api.mjs
│   │   │   ├── chatgpt-web.mjs
│   │   │   ├── claude-api.mjs
│   │   │   ├── claude-web.mjs
│   │   │   ├── custom-api.mjs
│   │   │   ├── deepseek-api.mjs
│   │   │   ├── moonshot-api.mjs
│   │   │   ├── moonshot-web.mjs
│   │   │   ├── ollama-api.mjs
│   │   │   ├── openai-api.mjs
│   │   │   ├── openai-token-params.mjs
│   │   │   ├── openrouter-api.mjs
│   │   │   ├── poe-web.mjs
│   │   │   ├── shared.mjs
│   │   │   └── waylaidwanderer-api.mjs
│   │   ├── clients/
│   │   │   ├── bard/
│   │   │   │   └── index.mjs
│   │   │   ├── bing/
│   │   │   │   ├── BingImageCreator.js
│   │   │   │   └── index.mjs
│   │   │   ├── claude/
│   │   │   │   └── index.mjs
│   │   │   └── poe/
│   │   │       ├── graphql/
│   │   │       │   ├── AddHumanMessageMutation.graphql
│   │   │       │   ├── AddMessageBreakMutation.graphql
│   │   │       │   ├── AutoSubscriptionMutation.graphql
│   │   │       │   ├── BioFragment.graphql
│   │   │       │   ├── ChatAddedSubscription.graphql
│   │   │       │   ├── ChatFragment.graphql
│   │   │       │   ├── ChatPaginationQuery.graphql
│   │   │       │   ├── ChatViewQuery.graphql
│   │   │       │   ├── DeleteHumanMessagesMutation.graphql
│   │   │       │   ├── HandleFragment.graphql
│   │   │       │   ├── LoginWithVerificationCodeMutation.graphql
│   │   │       │   ├── MessageAddedSubscription.graphql
│   │   │       │   ├── MessageDeletedSubscription.graphql
│   │   │       │   ├── MessageFragment.graphql
│   │   │       │   ├── MessageRemoveVoteMutation.graphql
│   │   │       │   ├── MessageSetVoteMutation.graphql
│   │   │       │   ├── SendVerificationCodeForLoginMutation.graphql
│   │   │       │   ├── ShareMessagesMutation.graphql
│   │   │       │   ├── SignupWithVerificationCodeMutation.graphql
│   │   │       │   ├── StaleChatUpdateMutation.graphql
│   │   │       │   ├── SummarizePlainPostQuery.graphql
│   │   │       │   ├── SummarizeQuotePostQuery.graphql
│   │   │       │   ├── SummarizeSharePostQuery.graphql
│   │   │       │   ├── UserSnippetFragment.graphql
│   │   │       │   ├── ViewerInfoQuery.graphql
│   │   │       │   ├── ViewerStateFragment.graphql
│   │   │       │   └── ViewerStateUpdatedSubscription.graphql
│   │   │       ├── index.mjs
│   │   │       └── websocket.js
│   │   ├── init-session.mjs
│   │   ├── local-session.mjs
│   │   └── wrappers.mjs
│   └── utils/
│       ├── change-children-font-size.mjs
│       ├── create-element-at-position.mjs
│       ├── crop-text.mjs
│       ├── ends-with-question-mark.mjs
│       ├── eventsource-parser.mjs
│       ├── fetch-bg.mjs
│       ├── fetch-sse.mjs
│       ├── get-client-position.mjs
│       ├── get-conversation-pairs.mjs
│       ├── get-core-content-text.mjs
│       ├── get-possible-element-by-query-selector.mjs
│       ├── index.mjs
│       ├── is-edge.mjs
│       ├── is-firefox.mjs
│       ├── is-mobile.mjs
│       ├── is-safari.mjs
│       ├── jwt-token-generator.mjs
│       ├── limited-fetch.mjs
│       ├── model-name-convert.mjs
│       ├── open-url.mjs
│       ├── parse-float-with-clamp.mjs
│       ├── parse-int-with-clamp.mjs
│       ├── set-element-position-in-viewport.mjs
│       ├── update-ref-height.mjs
│       └── wait-for-element-to-exist-and-select.mjs
└── tests/
    ├── setup/
    │   ├── browser-shim.mjs
    │   └── jsx-loader-hooks.mjs
    └── unit/
        ├── background/
        │   └── redact.test.mjs
        ├── config/
        │   ├── config-predicates.test.mjs
        │   └── user-config.test.mjs
        ├── content-script/
        │   └── selection-tools.test.mjs
        ├── helpers/
        │   ├── port.mjs
        │   └── sse-response.mjs
        ├── popup/
        │   └── import-data-cleanup.test.mjs
        ├── services/
        │   ├── apis/
        │   │   ├── azure-openai-api.test.mjs
        │   │   ├── claude-api.test.mjs
        │   │   ├── custom-api.test.mjs
        │   │   ├── openai-api-compat.test.mjs
        │   │   ├── openai-token-params.test.mjs
        │   │   ├── shared.test.mjs
        │   │   └── thin-adapters.test.mjs
        │   ├── handle-port-error.test.mjs
        │   ├── init-session.test.mjs
        │   ├── local-session.test.mjs
        │   └── wrappers-register.test.mjs
        ├── setup/
        │   └── browser-shim.test.mjs
        └── utils/
            ├── basic-guards.test.mjs
            ├── browser-detection.test.mjs
            ├── crop-text.test.mjs
            ├── eventsource-parser.test.mjs
            ├── fetch-sse.test.mjs
            ├── get-client-position.test.mjs
            ├── jwt-token-generator.test.mjs
            ├── model-name-convert.test.mjs
            └── set-element-position-in-viewport.test.mjs
Download .txt
SYMBOL INDEX (350 symbols across 101 files)

FILE: .github/workflows/scripts/update-coverage-badge.mjs
  function getBadgeColor (line 7) | function getBadgeColor(percentage) {
  function main (line 16) | function main() {

FILE: .github/workflows/scripts/verify-search-engine-configs.mjs
  function verify (line 143) | async function verify(errorTag, urls, headers, queryNames) {
  function main (line 184) | async function main() {

FILE: build.mjs
  function getBooleanEnv (line 18) | function getBooleanEnv(val, defaultValue) {
  function parseCacheCompressionOption (line 34) | function parseCacheCompressionOption(envVal) {
  function parseThreadWorkerCount (line 50) | function parseThreadWorkerCount(envValue, cpuCount) {
  constant PRODUCTION_POOL_TIMEOUT_MS (line 70) | let PRODUCTION_POOL_TIMEOUT_MS = 2000
  function resolveSassImplementation (line 88) | function resolveSassImplementation(mod) {
  function getSassImplementation (line 94) | async function getSassImplementation() {
  function deleteOldDir (line 115) | async function deleteOldDir() {
  function runWebpack (line 119) | async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, so...
  function zipFolder (line 466) | async function zipFolder(dir) {
  function copyFiles (line 507) | async function copyFiles(entryPoints, targetDir) {
  function ensureDevCssPlaceholders (line 533) | async function ensureDevCssPlaceholders(cssFiles) {
  function finishOutput (line 548) | async function finishOutput(outputDirSuffix, sourceBuildDir = outdir) {
  function build (line 613) | async function build() {

FILE: src/background/commands.mjs
  function registerCommands (line 4) | function registerCommands() {

FILE: src/background/index.mjs
  constant RECONNECT_CONFIG (line 61) | const RECONNECT_CONFIG = {
  function setPortProxy (line 67) | function setPortProxy(port, proxyTabId) {
  function executeApi (line 348) | async function executeApi(session, port, config) {

FILE: src/background/menus.mjs
  function refreshMenu (line 36) | function refreshMenu() {

FILE: src/background/redact.mjs
  constant SENSITIVE_KEYWORDS (line 1) | const SENSITIVE_KEYWORDS = [
  function isPromptOrSelectionLikeKey (line 12) | function isPromptOrSelectionLikeKey(lowerKey) {
  function redactSensitiveFields (line 24) | function redactSensitiveFields(obj, recursionDepth = 0, maxDepth = 5, se...

FILE: src/components/ConfirmButton/index.jsx
  function ConfirmButton (line 10) | function ConfirmButton({ onConfirm, text }) {

FILE: src/components/ConversationCard/index.jsx
  class ConversationItemData (line 42) | class ConversationItemData extends Object {
    method constructor (line 48) | constructor(type, content, done = false) {
  function ConversationCard (line 56) | function ConversationCard(props) {

FILE: src/components/ConversationItem/index.jsx
  function AnswerTitle (line 9) | function AnswerTitle({ descName }) {
  function ConversationItem (line 19) | function ConversationItem({ type, content, descName, onRetry }) {

FILE: src/components/CopyButton/index.jsx
  function CopyButton (line 12) | function CopyButton({ className, contentFn, size }) {

FILE: src/components/DecisionCard/index.jsx
  function DecisionCard (line 9) | function DecisionCard(props) {

FILE: src/components/DeleteButton/index.jsx
  function DeleteButton (line 12) | function DeleteButton({ onConfirm, size, text }) {

FILE: src/components/FloatingToolbar/index.jsx
  function FloatingToolbar (line 13) | function FloatingToolbar(props) {

FILE: src/components/InputBox/index.jsx
  function InputBox (line 7) | function InputBox({ onSubmit, enabled, postMessage, reverseResizeDir }) {

FILE: src/components/MarkdownRender/Hyperlink.jsx
  function Hyperlink (line 4) | function Hyperlink({ href, children }) {

FILE: src/components/MarkdownRender/Pre.jsx
  function Pre (line 6) | function Pre({ className, children }) {

FILE: src/components/MarkdownRender/markdown-without-katex.jsx
  function MarkdownRender (line 111) | function MarkdownRender(props) {

FILE: src/components/MarkdownRender/markdown.jsx
  function MarkdownRender (line 114) | function MarkdownRender(props) {

FILE: src/components/ReadButton/index.jsx
  function ReadButton (line 15) | function ReadButton({ className, contentFn, size }) {

FILE: src/config/index.mjs
  function getNavigatorLanguage (line 666) | function getNavigatorLanguage() {
  function isUsingChatgptWebModel (line 672) | function isUsingChatgptWebModel(configOrSession) {
  function isUsingClaudeWebModel (line 676) | function isUsingClaudeWebModel(configOrSession) {
  function isUsingMoonshotWebModel (line 680) | function isUsingMoonshotWebModel(configOrSession) {
  function isUsingBingWebModel (line 684) | function isUsingBingWebModel(configOrSession) {
  function isUsingMultiModeModel (line 688) | function isUsingMultiModeModel(configOrSession) {
  function isUsingGeminiWebModel (line 692) | function isUsingGeminiWebModel(configOrSession) {
  function isUsingChatgptApiModel (line 696) | function isUsingChatgptApiModel(configOrSession) {
  function isUsingGptCompletionApiModel (line 700) | function isUsingGptCompletionApiModel(configOrSession) {
  function isUsingOpenAiApiModel (line 704) | function isUsingOpenAiApiModel(configOrSession) {
  function isUsingClaudeApiModel (line 708) | function isUsingClaudeApiModel(configOrSession) {
  function isUsingMoonshotApiModel (line 712) | function isUsingMoonshotApiModel(configOrSession) {
  function isUsingDeepSeekApiModel (line 716) | function isUsingDeepSeekApiModel(configOrSession) {
  function isUsingOpenRouterApiModel (line 720) | function isUsingOpenRouterApiModel(configOrSession) {
  function isUsingAimlApiModel (line 724) | function isUsingAimlApiModel(configOrSession) {
  function isUsingChatGLMApiModel (line 728) | function isUsingChatGLMApiModel(configOrSession) {
  function isUsingOllamaApiModel (line 732) | function isUsingOllamaApiModel(configOrSession) {
  function isUsingAzureOpenAiApiModel (line 736) | function isUsingAzureOpenAiApiModel(configOrSession) {
  function isUsingGithubThirdPartyApiModel (line 740) | function isUsingGithubThirdPartyApiModel(configOrSession) {
  function isUsingCustomModel (line 744) | function isUsingCustomModel(configOrSession) {
  function isUsingCustomNameOnlyModel (line 751) | function isUsingCustomNameOnlyModel(configOrSession) {
  function getPreferredLanguageKey (line 755) | async function getPreferredLanguageKey() {
  function getUserConfig (line 765) | async function getUserConfig() {
  function setUserConfig (line 812) | async function setUserConfig(value) {
  function setAccessToken (line 816) | async function setAccessToken(accessToken) {
  constant TOKEN_DURATION (line 820) | const TOKEN_DURATION = 30 * 24 * 3600 * 1000
  function clearOldAccessToken (line 822) | async function clearOldAccessToken() {

FILE: src/config/language.mjs
  function getUserLanguage (line 14) | async function getUserLanguage() {
  function getUserLanguageNative (line 18) | async function getUserLanguageNative() {
  function getPreferredLanguage (line 22) | async function getPreferredLanguage() {
  function getPreferredLanguageNative (line 28) | async function getPreferredLanguageNative() {

FILE: src/content-script/index.jsx
  function mountComponent (line 38) | async function mountComponent(siteName, siteConfig) {
  function getInput (line 177) | async function getInput(inputQuery) {
  function prepareForSelectionTools (line 270) | async function prepareForSelectionTools() {
  function prepareForSelectionToolsTouch (line 382) | async function prepareForSelectionToolsTouch() {
  function prepareForRightClickMenu (line 449) | async function prepareForRightClickMenu() {
  function prepareForStaticCard (line 521) | async function prepareForStaticCard() {
  function overwriteAccessToken (line 584) | async function overwriteAccessToken() {
  function getClaudeSessionKey (line 659) | async function getClaudeSessionKey() {
  function prepareForJumpBackNotification (line 677) | async function prepareForJumpBackNotification() {
  function ensureChatGptPortListenerRegistered (line 861) | function ensureChatGptPortListenerRegistered() {
  function run (line 917) | async function run() {
  function manageChatGptTabState (line 986) | async function manageChatGptTabState() {

FILE: src/content-script/site-adapters/github/index.mjs
  function parseGitHubIssueData (line 27) | function parseGitHubIssueData() {
  function createChatGPtSummaryPrompt (line 83) | function createChatGPtSummaryPrompt(issueData, isIssue = true) {

FILE: src/content-script/site-adapters/youtube/index.mjs
  function replaceHtmlEntities (line 5) | function replaceHtmlEntities(htmlString) {

FILE: src/hooks/use-clamp-window-size.mjs
  function useClampWindowSize (line 3) | function useClampWindowSize(widthRange = [0, Infinity], heightRange = [0...

FILE: src/hooks/use-config.mjs
  function useConfig (line 5) | function useConfig(initFn, ignoreSession = true) {

FILE: src/hooks/use-theme.mjs
  function useTheme (line 4) | function useTheme() {

FILE: src/hooks/use-window-size.mjs
  function useWindowSize (line 5) | function useWindowSize() {

FILE: src/hooks/use-window-theme.mjs
  function useWindowTheme (line 3) | function useWindowTheme() {

FILE: src/pages/IndependentPanel/App.jsx
  function App (line 20) | function App() {

FILE: src/popup/Popup.jsx
  function Footer (line 23) | function Footer({ currentVersion, latestVersion }) {
  function Popup (line 60) | function Popup() {

FILE: src/popup/sections/AdvancedPart.jsx
  function ApiParams (line 12) | function ApiParams({ config, updateConfig }) {
  function ApiUrl (line 68) | function ApiUrl({ config, updateConfig }) {
  function Others (line 126) | function Others({ config, updateConfig }) {
  function AdvancedPart (line 224) | function AdvancedPart({ config, updateConfig }) {

FILE: src/popup/sections/ApiModes.jsx
  function ApiModes (line 33) | function ApiModes({ config, updateConfig }) {

FILE: src/popup/sections/FeaturePages.jsx
  function FeaturePages (line 12) | function FeaturePages({ config, updateConfig }) {

FILE: src/popup/sections/GeneralPart.jsx
  function isUsingSpecialCustomModel (line 41) | function isUsingSpecialCustomModel(configOrSession) {
  function GeneralPart (line 45) | function GeneralPart({ config, updateConfig, setTabIndex }) {

FILE: src/popup/sections/ModulesPart.jsx
  function ModulesPart (line 13) | function ModulesPart({ config, updateConfig }) {

FILE: src/popup/sections/SelectionTools.jsx
  function SelectionTools (line 20) | function SelectionTools({ config, updateConfig }) {

FILE: src/popup/sections/SiteAdapters.jsx
  function SiteAdapters (line 23) | function SiteAdapters({ config, updateConfig }) {

FILE: src/popup/sections/import-data-cleanup.mjs
  function prepareImportData (line 6) | function prepareImportData(data) {
  function importDataIntoStorage (line 26) | async function importDataIntoStorage(storageArea, data) {

FILE: src/services/apis/aiml-api.mjs
  function generateAnswersWithAimlApi (line 9) | async function generateAnswersWithAimlApi(port, question, session, apiKe...

FILE: src/services/apis/azure-openai-api.mjs
  function generateAnswersWithAzureOpenaiApi (line 13) | async function generateAnswersWithAzureOpenaiApi(port, question, session) {

FILE: src/services/apis/bard-web.mjs
  function generateAnswersWithBardWebApi (line 10) | async function generateAnswersWithBardWebApi(port, question, session, co...

FILE: src/services/apis/bing-web.mjs
  function generateAnswersWithBingWebApi (line 13) | async function generateAnswersWithBingWebApi(

FILE: src/services/apis/chatglm-api.mjs
  function generateAnswersWithChatGLMApi (line 10) | async function generateAnswersWithChatGLMApi(port, question, session) {

FILE: src/services/apis/chatgpt-web.mjs
  function request (line 14) | async function request(token, method, path, data) {
  function sendMessageFeedback (line 29) | async function sendMessageFeedback(token, data) {
  function setConversationProperty (line 33) | async function setConversationProperty(token, conversationId, propertyOb...
  function deleteConversation (line 37) | async function deleteConversation(token, conversationId) {
  function sendModerations (line 41) | async function sendModerations(token, question, conversationId, messageI...
  function getModels (line 50) | async function getModels(token) {
  function getRequirements (line 55) | async function getRequirements(accessToken) {
  function getArkoseToken (line 64) | async function getArkoseToken(config) {
  function generateProofToken (line 99) | function generateProofToken(seed, diff, userAgent) {
  function isNeedWebsocket (line 152) | async function isNeedWebsocket(accessToken) {
  function sendWebsocketConversation (line 158) | async function sendWebsocketConversation(accessToken, options) {
  function stopWebsocketConversation (line 165) | async function stopWebsocketConversation(accessToken, conversationId, ws...
  function registerWebsocket (line 182) | async function registerWebsocket(accessToken) {
  function generateAnswersWithChatgptWebApi (line 214) | async function generateAnswersWithChatgptWebApi(port, question, session,...

FILE: src/services/apis/claude-api.mjs
  function generateAnswersWithClaudeApi (line 13) | async function generateAnswersWithClaudeApi(port, question, session) {

FILE: src/services/apis/claude-web.mjs
  function generateAnswersWithClaudeWebApi (line 11) | async function generateAnswersWithClaudeWebApi(port, question, session, ...

FILE: src/services/apis/custom-api.mjs
  function generateAnswersWithCustomApi (line 23) | async function generateAnswersWithCustomApi(

FILE: src/services/apis/deepseek-api.mjs
  function generateAnswersWithDeepSeekApi (line 9) | async function generateAnswersWithDeepSeekApi(port, question, session, a...

FILE: src/services/apis/moonshot-api.mjs
  function generateAnswersWithMoonshotCompletionApi (line 9) | async function generateAnswersWithMoonshotCompletionApi(port, question, ...

FILE: src/services/apis/moonshot-web.mjs
  class MoonshotWeb (line 7) | class MoonshotWeb {
    method constructor (line 46) | constructor({ config, fetch }) {
    method models (line 58) | models() {
    method defaultModel (line 65) | defaultModel() {
    method sendMessage (line 78) | async sendMessage(message, { conversation = null, temporary = true, .....
    method request (line 112) | request(endpoint, options) {
    method init (line 137) | async init() {
    method startConversation (line 181) | async startConversation(message, params = {}) {
    method getConversation (line 214) | async getConversation(id) {
  class Conversation (line 237) | class Conversation {
    method constructor (line 308) | constructor(
    method toJSON (line 341) | toJSON() {
    method retry (line 356) | async retry(params) {
    method sendMessage (line 366) | async sendMessage(
    method delete (line 453) | async delete() {
    method getMessages (line 469) | getMessages() {
  function errorHandle (line 482) | function errorHandle(msg) {
  class Message (line 511) | class Message {
    method constructor (line 519) | constructor(
    method toJSON (line 539) | toJSON() {
    method createdAt (line 547) | get createdAt() {
    method updatedAt (line 555) | get updatedAt() {
    method editedAt (line 563) | get editedAt() {
    method isBot (line 570) | get isBot() {
  function generateAnswersWithMoonshotWebApi (line 581) | async function generateAnswersWithMoonshotWebApi(port, question, session...

FILE: src/services/apis/ollama-api.mjs
  function generateAnswersWithOllamaApi (line 10) | async function generateAnswersWithOllamaApi(port, question, session) {

FILE: src/services/apis/openai-api.mjs
  function generateAnswersWithGptCompletionApi (line 17) | async function generateAnswersWithGptCompletionApi(port, question, sessi...
  function generateAnswersWithOpenAiApi (line 99) | async function generateAnswersWithOpenAiApi(port, question, session, api...
  function generateAnswersWithOpenAiApiCompat (line 112) | async function generateAnswersWithOpenAiApiCompat(

FILE: src/services/apis/openai-token-params.mjs
  constant GPT5_CHAT_COMPLETIONS_MODEL_PATTERN (line 1) | const GPT5_CHAT_COMPLETIONS_MODEL_PATTERN = /^gpt-5([.-]|$)/
  function shouldUseMaxCompletionTokens (line 3) | function shouldUseMaxCompletionTokens(provider, model) {
  function getChatCompletionsTokenParams (line 16) | function getChatCompletionsTokenParams(provider, model, maxResponseToken...

FILE: src/services/apis/openrouter-api.mjs
  function generateAnswersWithOpenRouterApi (line 9) | async function generateAnswersWithOpenRouterApi(port, question, session,...

FILE: src/services/apis/poe-web.mjs
  function generateAnswersWithPoeWebApi (line 10) | async function generateAnswersWithPoeWebApi(port, question, session, mod...

FILE: src/services/apis/shared.mjs
  function setAbortController (line 18) | function setAbortController(port, onStop, onDisconnect) {
  function pushRecord (line 51) | function pushRecord(session, question, answer) {

FILE: src/services/apis/waylaidwanderer-api.mjs
  function generateAnswersWithWaylaidwandererApi (line 11) | async function generateAnswersWithWaylaidwandererApi(port, question, ses...

FILE: src/services/clients/bard/index.mjs
  class Bard (line 3) | class Bard {
    method constructor (line 6) | constructor(cookies) {
    method ParseResponse (line 10) | ParseResponse(text) {
    method GetRequestParams (line 65) | async GetRequestParams() {
    method ask (line 86) | async ask(prompt, conversationObj) {
    method send (line 90) | async send(prompt, conversationObj) {

FILE: src/services/clients/bing/BingImageCreator.js
  class BingImageCreator (line 1) | class BingImageCreator {
    method constructor (line 6) | constructor(options) {
    method setOptions (line 14) | setOptions(options) {
    method getValidIPv4 (line 72) | static getValidIPv4(ip) {
    method fetchOptions (line 103) | get fetchOptions() {
    method decodeHtmlLite (line 159) | static decodeHtmlLite(html) {
    method removeHtmlTagLite (line 177) | static removeHtmlTagLite(html, tag, tagId) {
    method sleep (line 235) | static sleep(ms) {
    method genImagePage (line 254) | async genImagePage(prompt, messageId) {
    method pollingImgRequest (line 319) | async pollingImgRequest(pollingUrl, onProgress) {
    method genImageList (line 370) | async genImageList(prompt, messageId, removeSizeLimit, onProgress) {
    method createImageIframe (line 394) | createImageIframe(src, isDoc) {
    method rewriteHtml (line 408) | rewriteHtml(html) {
    method renderImageIframe (line 418) | renderImageIframe(containerHtml, resultHtml) {
    method genImageIframeSsr (line 443) | async genImageIframeSsr(prompt, messageId, onProgress) {
    method genImageIframeSsrLite (line 464) | async genImageIframeSsrLite(prompt, messageId, onProgress) {
    method genImageIframeCsr (line 479) | async genImageIframeCsr(prompt, messageId) {
    method inlineImagePattern (line 487) | static get inlineImagePattern() {
    method parseInlineGenerativeImage (line 500) | static parseInlineGenerativeImage(message) {

FILE: src/services/clients/bing/index.mjs
  class BingAIClient (line 14) | class BingAIClient {
    method constructor (line 15) | constructor(options) {
    method setOptions (line 23) | setOptions(options) {
    method getValidIPv4 (line 47) | static getValidIPv4(ip) {
    method createNewConversation (line 74) | async createNewConversation() {
    method createWebSocketConnection (line 137) | async createWebSocketConnection(encryptedConversationSignature) {
    method cleanupWebSocketConnection (line 202) | static cleanupWebSocketConnection(ws) {
    method sendMessage (line 207) | async sendMessage(message, opts = {}) {
    method getMessagesForConversation (line 648) | static getMessagesForConversation(messages, parentMessageId) {

FILE: src/services/clients/claude/index.mjs
  class Claude (line 13) | class Claude {
    method constructor (line 54) | constructor({ sessionKey, proxy, fetch }) {
    method models (line 89) | models() {
    method totalTokens (line 97) | totalTokens(model) {
    method defaultModel (line 111) | defaultModel() {
    method sendMessage (line 133) | async sendMessage(message, { conversation = null, temporary = true, .....
    method request (line 163) | request(endpoint, options) {
    method init (line 188) | async init() {
    method getOrganizations (line 218) | async getOrganizations() {
    method clearConversations (line 247) | async clearConversations() {
    method startConversation (line 269) | async startConversation(message, params = {}) {
    method getConversation (line 327) | async getConversation(id) {
    method getConversations (line 340) | async getConversations() {
    method uploadFile (line 375) | async uploadFile(file) {
  class Conversation (line 431) | class Conversation {
    method constructor (line 508) | constructor(
    method toJSON (line 539) | toJSON() {
    method retry (line 555) | async retry(params) {
    method sendMessage (line 565) | async sendMessage(
    method rename (line 657) | async rename(title) {
    method delete (line 678) | async delete() {
    method getInfo (line 708) | async getInfo() {
    method getFiles (line 728) | getFiles() {
    method getMessages (line 739) | getMessages() {
    method #formatMessages (line 749) | #formatMessages(message_key) {
  function readStream (line 771) | async function readStream(response, progressCallback) {
  function readAsText (line 818) | async function readAsText(file) {
  function errorHandle (line 834) | function errorHandle(msg) {
  function uuid (line 847) | function uuid() {
  class Message (line 921) | class Message {
    method constructor (line 929) | constructor(
    method toJSON (line 949) | toJSON() {
    method createdAt (line 957) | get createdAt() {
    method updatedAt (line 965) | get updatedAt() {
    method editedAt (line 973) | get editedAt() {
    method isBot (line 980) | get isBot() {
    method sendFeedback (line 997) | async sendFeedback(type, reason = '') {

FILE: src/services/clients/poe/index.mjs
  class PoeAiClient (line 16) | class PoeAiClient {
    method constructor (line 17) | constructor(chatId = null) {
    method ask (line 29) | async ask(message, model, onMessage, onComplete) {
    method close (line 47) | async close() {
    method getFormkey (line 54) | async getFormkey() {
    method getCredentials (line 67) | async getCredentials() {
    method subscribe (line 84) | async subscribe() {
    method makeRequest (line 107) | async makeRequest(request) {
    method getChatId (line 118) | async getChatId(bot) {
    method initBot (line 133) | async initBot(bot) {
    method breakMsg (line 163) | async breakMsg() {
    method sendMsg (line 170) | async sendMsg(query) {

FILE: src/services/init-session.mjs
  function initSession (line 43) | function initSession({

FILE: src/services/wrappers.mjs
  function getChatGptAccessToken (line 12) | async function getChatGptAccessToken() {
  function getBingAccessToken (line 40) | async function getBingAccessToken() {
  function getBardCookies (line 44) | async function getBardCookies() {
  function getClaudeSessionKey (line 50) | async function getClaudeSessionKey() {
  function handlePortError (line 54) | function handlePortError(session, port, err) {
  function registerPortListener (line 96) | function registerPortListener(executor) {

FILE: src/utils/change-children-font-size.mjs
  function changeChildrenFontSize (line 1) | function changeChildrenFontSize(element, size) {

FILE: src/utils/create-element-at-position.mjs
  function createElementAtPosition (line 1) | function createElementAtPosition(x = 0, y = 0, zIndex = 2147483647) {

FILE: src/utils/crop-text.mjs
  function cropText (line 31) | async function cropText(

FILE: src/utils/ends-with-question-mark.mjs
  function endsWithQuestionMark (line 1) | function endsWithQuestionMark(question) {

FILE: src/utils/eventsource-parser.mjs
  function createParser (line 3) | function createParser(onParse) {
  constant BOM (line 133) | const BOM = [239, 187, 191]
  function hasBom (line 134) | function hasBom(buffer) {

FILE: src/utils/fetch-bg.mjs
  function fetchBg (line 8) | function fetchBg(input, init) {

FILE: src/utils/fetch-sse.mjs
  function fetchSSE (line 3) | async function fetchSSE(resource, options) {

FILE: src/utils/get-client-position.mjs
  function getClientPosition (line 1) | function getClientPosition(e) {

FILE: src/utils/get-conversation-pairs.mjs
  function getConversationPairs (line 1) | function getConversationPairs(records, isCompletion) {

FILE: src/utils/get-core-content-text.mjs
  function getArea (line 16) | function getArea(e) {
  function findLargestElement (line 21) | function findLargestElement(e) {
  function getTextFrom (line 46) | function getTextFrom(e) {
  function postProcessText (line 50) | function postProcessText(text) {
  function getCoreContentText (line 59) | function getCoreContentText() {

FILE: src/utils/get-possible-element-by-query-selector.mjs
  function getPossibleElementByQuerySelector (line 1) | function getPossibleElementByQuerySelector(queryArray) {

FILE: src/utils/is-edge.mjs
  function isEdge (line 1) | function isEdge() {

FILE: src/utils/is-firefox.mjs
  function isFirefox (line 1) | function isFirefox() {

FILE: src/utils/is-mobile.mjs
  function isMobile (line 3) | function isMobile() {

FILE: src/utils/is-safari.mjs
  function isSafari (line 1) | function isSafari() {

FILE: src/utils/jwt-token-generator.mjs
  function generateToken (line 6) | function generateToken(apiKey, timeoutSeconds) {
  function shouldRegenerateToken (line 31) | function shouldRegenerateToken() {
  function getToken (line 36) | function getToken(apiKey) {

FILE: src/utils/limited-fetch.mjs
  function limitedFetch (line 3) | async function limitedFetch(url, maxBytes) {

FILE: src/utils/model-name-convert.mjs
  function modelNameToDesc (line 3) | function modelNameToDesc(modelName, t, extraCustomModelName = '') {
  function modelNameToPresetPart (line 31) | function modelNameToPresetPart(modelName) {
  function modelNameToCustomPart (line 39) | function modelNameToCustomPart(modelName) {
  function modelNameToValue (line 47) | function modelNameToValue(modelName) {
  function getModelValue (line 53) | function getModelValue(configOrSession) {
  function isCustomModelName (line 60) | function isCustomModelName(modelName) {
  function modelNameToApiMode (line 64) | function modelNameToApiMode(modelName) {
  function apiModeToModelName (line 84) | function apiModeToModelName(apiMode) {
  function getApiModesFromConfig (line 96) | function getApiModesFromConfig(config, onlyActive) {
  function getApiModesStringArrayFromConfig (line 122) | function getApiModesStringArrayFromConfig(config, onlyActive) {
  function isApiModeSelected (line 126) | function isApiModeSelected(apiMode, configOrSession) {
  function isUsingModelName (line 134) | function isUsingModelName(modelName, configOrSession) {
  function getModelNameGroup (line 150) | function getModelNameGroup(modelName) {
  function getApiModeGroup (line 158) | function getApiModeGroup(apiMode) {
  function isInApiModeGroup (line 162) | function isInApiModeGroup(apiModeGroup, configOrSession) {

FILE: src/utils/open-url.mjs
  function openUrl (line 3) | function openUrl(url) {

FILE: src/utils/parse-float-with-clamp.mjs
  function parseFloatWithClamp (line 1) | function parseFloatWithClamp(value, defaultValue, min, max) {

FILE: src/utils/parse-int-with-clamp.mjs
  function parseIntWithClamp (line 1) | function parseIntWithClamp(value, defaultValue, min, max) {

FILE: src/utils/set-element-position-in-viewport.mjs
  function setElementPositionInViewport (line 1) | function setElementPositionInViewport(element, x = 0, y = 0) {

FILE: src/utils/update-ref-height.mjs
  function updateRefHeight (line 1) | function updateRefHeight(ref) {

FILE: src/utils/wait-for-element-to-exist-and-select.mjs
  function waitForElementToExistAndSelect (line 1) | function waitForElementToExistAndSelect(selector, timeout = 0) {

FILE: tests/setup/browser-shim.mjs
  method addListener (line 6) | addListener(listener) {
  method removeListener (line 9) | removeListener(listener) {
  method hasListener (line 12) | hasListener(listener) {
  method _trigger (line 15) | _trigger(...args) {
  method _clear (line 20) | _clear() {
  method _size (line 23) | _size() {
  method get (line 63) | get(keys, callback) {
  method set (line 71) | set(items, callback) {
  method remove (line 79) | remove(keys, callback) {
  method clear (line 90) | clear(callback) {
  method query (line 101) | query(_queryInfo, callback) {
  method sendMessage (line 109) | sendMessage(_tabId, _message, optionsOrCallback, callback) {
  method create (line 125) | create(_createData, callback) {
  method update (line 133) | update(_windowId, _updateInfo, callback) {
  method sendMessage (line 146) | sendMessage(_message, optionsOrCallback, callback) {
  method getURL (line 159) | getURL(path) {
  method setStorage (line 195) | setStorage(values) {
  method replaceStorage (line 198) | replaceStorage(values) {
  method clearStorage (line 201) | clearStorage() {
  method getStorage (line 204) | getStorage() {
  method resetEvents (line 207) | resetEvents() {

FILE: tests/setup/jsx-loader-hooks.mjs
  constant JSX_RE (line 8) | const JSX_RE = /<[A-Z][A-Za-z0-9]*[\s/>]/
  constant CJS_REEXPORT (line 11) | const CJS_REEXPORT = new Set(['countries-list'])
  function load (line 13) | async function load(url, context, nextLoad) {

FILE: tests/unit/config/user-config.test.mjs
  constant THIRTY_DAYS_MS (line 6) | const THIRTY_DAYS_MS = 30 * 24 * 3600 * 1000

FILE: tests/unit/helpers/port.mjs
  function createFakePort (line 1) | function createFakePort() {

FILE: tests/unit/helpers/sse-response.mjs
  function createMockSseResponse (line 3) | function createMockSseResponse(chunks, options = {}) {

FILE: tests/unit/popup/import-data-cleanup.test.mjs
  method set (line 78) | async set(data) {
  method remove (line 81) | async remove(keys) {
  method set (line 99) | async set() {
  method remove (line 103) | async remove(keys) {
  method set (line 120) | async set(data) {
  method remove (line 123) | async remove() {

FILE: tests/unit/services/init-session.test.mjs
  constant UUID_RE (line 5) | const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}...

FILE: tests/unit/services/local-session.test.mjs
  constant UUID_RE (line 13) | const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}...

FILE: tests/unit/services/wrappers-register.test.mjs
  method addListener (line 10) | addListener(listener) {
  method removeListener (line 13) | removeListener(listener) {
  method getAll (line 20) | getAll(query, callback) {
  method get (line 28) | get(query, callback) {
  function triggerConnect (line 51) | function triggerConnect(port) {

FILE: tests/unit/utils/basic-guards.test.mjs
  constant PARSE_INT_DEFAULT (line 8) | const PARSE_INT_DEFAULT = 5
  constant PARSE_INT_MIN (line 9) | const PARSE_INT_MIN = 1
  constant PARSE_INT_MAX (line 10) | const PARSE_INT_MAX = 10

FILE: tests/unit/utils/get-client-position.test.mjs
  method getBoundingClientRect (line 7) | getBoundingClientRect() {
  method getBoundingClientRect (line 17) | getBoundingClientRect() {
Condensed preview — 227 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (990K chars).
[
  {
    "path": ".eslintrc.json",
    "chars": 423,
    "preview": "{\n  \"env\": {\n    \"browser\": true,\n    \"es2021\": true\n  },\n  \"extends\": [\"eslint:recommended\", \"plugin:react/recommended\""
  },
  {
    "path": ".gitattributes",
    "chars": 42,
    "preview": "src/services/clients/** linguist-vendored\n"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "chars": 78,
    "preview": "See https://github.com/ChatGPTBox-dev/chatGPTBox/wiki/Development&Contributing"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report---问题报告.md",
    "chars": 738,
    "preview": "---\nname: Bug report / 问题报告\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describ"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request---新功能请求.md",
    "chars": 513,
    "preview": "---\nname: Feature request / 新功能请求\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is "
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 182,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n  "
  },
  {
    "path": ".github/workflows/pr-tests.yml",
    "chars": 2963,
    "preview": "name: pr-tests\n\non:\n  pull_request:\n    types:\n      - \"opened\"\n      - \"reopened\"\n      - \"synchronize\"\n    paths:\n    "
  },
  {
    "path": ".github/workflows/pre-release-build.yml",
    "chars": 2347,
    "preview": "name: pre-release\non:\n  workflow_dispatch:\n#  push:\n#    branches:\n#      - master\n#    paths:\n#      - \"src/**\"\n#      "
  },
  {
    "path": ".github/workflows/scripts/update-coverage-badge.mjs",
    "chars": 1274,
    "preview": "import fs from 'node:fs'\nimport path from 'node:path'\n\nconst coverageSummaryPath = 'coverage/coverage-summary.json'\ncons"
  },
  {
    "path": ".github/workflows/scripts/verify-search-engine-configs.mjs",
    "chars": 6298,
    "preview": "import { JSDOM } from 'jsdom'\nimport fetch, { Headers } from 'node-fetch'\n\nconst config = {\n  google: {\n    inputQuery: "
  },
  {
    "path": ".github/workflows/tagged-release.yml",
    "chars": 2116,
    "preview": "name: tagged-release\non:\n  push:\n    tags:\n      - \"v*\"\n\npermissions:\n  id-token: \"write\"\n  contents: \"write\"\nenv:\n  GH_"
  },
  {
    "path": ".github/workflows/verify-configs.yml",
    "chars": 304,
    "preview": "name: verify-configs\non:\n  workflow_dispatch:\n  schedule:\n    - cron: \"0 6 * * *\"\n\njobs:\n  verify_configs:\n    runs-on: "
  },
  {
    "path": ".gitignore",
    "chars": 74,
    "preview": ".idea/\n.vscode/\nnode_modules/\nbuild/\n.coverage/\ncoverage/\n.DS_Store\n*.zip\n"
  },
  {
    "path": ".nvmrc",
    "chars": 3,
    "preview": "22\n"
  },
  {
    "path": ".prettierignore",
    "chars": 45,
    "preview": "build/\nsrc/manifest.json\nsrc/manifest.v2.json"
  },
  {
    "path": ".prettierrc",
    "chars": 249,
    "preview": "{\n  \"printWidth\": 100,\n  \"semi\": false,\n  \"tabWidth\": 2,\n  \"singleQuote\": true,\n  \"trailingComma\": \"all\",\n  \"bracketSpac"
  },
  {
    "path": "AGENTS.md",
    "chars": 16300,
    "preview": "# ChatGPTBox - Browser Extension\n\nChatGPTBox is a cross-platform browser extension that deeply integrates ChatGPT and ot"
  },
  {
    "path": "CURRENT_CHANGE.md",
    "chars": 4283,
    "preview": "Long time no see — ChatGPTBox is back! Nearly every feature that had broken due to page updates or API changes has been "
  },
  {
    "path": "LICENSE",
    "chars": 1091,
    "preview": "MIT License\n\nCopyright (c) 2022 josStorer\nCopyright (c) 2022 wong2\n\nPermission is hereby granted, free of charge, to any"
  },
  {
    "path": "README.md",
    "chars": 7184,
    "preview": "<p align=\"center\">\n    <img src=\"./src/logo.png\">\n</p>\n\n<h1 align=\"center\">ChatGPT Box</h1>\n\n<div align=\"center\">\n\nDeep "
  },
  {
    "path": "README_IN.md",
    "chars": 6778,
    "preview": "<p align=\"center\">\n    <img src=\"./src/logo.png\">\n</p>\n\n<h1 align=\"center\">ChatGPT Box</h1>\n\n<div align=\"center\">\n\nInteg"
  },
  {
    "path": "README_JA.md",
    "chars": 5745,
    "preview": "<p align=\"center\">\n    <img src=\"./src/logo.png\">\n</p>\n\n<h1 align=\"center\">ChatGPT Box</h1>\n\n<div align=\"center\">\n\n深い Ch"
  },
  {
    "path": "README_TR.md",
    "chars": 7141,
    "preview": "<p align=\"center\">\r\n    <img src=\"./src/logo.png\">\r\n</p>\r\n\r\n<h1 align=\"center\">ChatGPT Box</h1>\r\n\r\n<div align=\"center\">\r"
  },
  {
    "path": "README_ZH.md",
    "chars": 5877,
    "preview": "<p align=\"center\">\n    <img src=\"./src/logo.png\">\n</p>\n\n<h1 align=\"center\">ChatGPT Box</h1>\n\n<div align=\"center\">\n\n将Chat"
  },
  {
    "path": "badges/coverage.json",
    "chars": 89,
    "preview": "{\n  \"schemaVersion\": 1,\n  \"label\": \"coverage\",\n  \"message\": \"17.69%\",\n  \"color\": \"red\"\n}\n"
  },
  {
    "path": "build.mjs",
    "chars": 22361,
    "preview": "import archiver from 'archiver'\nimport fs from 'fs-extra'\nimport path from 'path'\nimport webpack from 'webpack'\nimport o"
  },
  {
    "path": "package.json",
    "chars": 3510,
    "preview": "{\n  \"name\": \"chatgptbox\",\n  \"engines\": {\n    \"node\": \">=22\"\n  },\n  \"scripts\": {\n    \"build\": \"node build.mjs --productio"
  },
  {
    "path": "safari/appdmg.json",
    "chars": 239,
    "preview": "{\n  \"title\": \"Fission - ChatBox\",\n  \"icon\": \"../src/logo.png\",\n  \"contents\": [\n    { \"x\": 448, \"y\": 344, \"type\": \"link\","
  },
  {
    "path": "safari/build.sh",
    "chars": 737,
    "preview": "git apply safari/project.pre.patch\nnpm run build\nxcrun safari-web-extension-converter ./build/firefox \\\n --project-locat"
  },
  {
    "path": "safari/export-options.plist",
    "chars": 240,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "safari/project.patch",
    "chars": 162,
    "preview": "--- a/build/safari/Fission - ChatBox/Fission - ChatBox.xcodeproj/project.pbxproj\n+++ b/build/safari/Fission - ChatBox/Fi"
  },
  {
    "path": "safari/project.pre.patch",
    "chars": 464,
    "preview": "--- a/src/manifest.v2.json\n+++ b/src/manifest.v2.json\n@@ -1,5 +1,5 @@\n {\n-  \"name\": \"ChatGPTBox\",\n+  \"name\": \"Fission - "
  },
  {
    "path": "safari/project_developer.patch",
    "chars": 7450,
    "preview": "--- a/build/safari/Fission - ChatBox/Fission - ChatBox.xcodeproj/project.pbxproj\n+++ b/build/safari/Fission - ChatBox/Fi"
  },
  {
    "path": "src/_locales/de/main.json",
    "chars": 11836,
    "preview": "{\n  \"General\": \"Allgemein\",\n  \"Selection Tools\": \"Auswahlwerkzeuge\",\n  \"Sites\": \"Webseiten\",\n  \"Advanced\": \"Erweiterte E"
  },
  {
    "path": "src/_locales/en/main.json",
    "chars": 11019,
    "preview": "{\n  \"General\": \"General\",\n  \"Selection Tools\": \"Selection Tools\",\n  \"Sites\": \"Sites\",\n  \"Advanced\": \"Advanced\",\n  \"Donat"
  },
  {
    "path": "src/_locales/es/main.json",
    "chars": 12031,
    "preview": "{\n  \"General\": \"General\",\n  \"Selection Tools\": \"Herramientas de selección\",\n  \"Sites\": \"Adaptaciones de sitios\",\n  \"Adva"
  },
  {
    "path": "src/_locales/fr/main.json",
    "chars": 12041,
    "preview": "{\n  \"General\": \"Général\",\n  \"Selection Tools\": \"Outils de sélection\",\n  \"Sites\": \"Sites\",\n  \"Advanced\": \"Avancé\",\n  \"Don"
  },
  {
    "path": "src/_locales/i18n-react.mjs",
    "chars": 285,
    "preview": "import i18n from 'i18next'\nimport { initReactI18next } from 'react-i18next'\nimport { resources } from './resources'\n\ni18"
  },
  {
    "path": "src/_locales/i18n.mjs",
    "chars": 117,
    "preview": "import i18n from 'i18next'\nimport { resources } from './resources'\n\ni18n.init({\n  resources,\n  fallbackLng: 'en',\n})\n"
  },
  {
    "path": "src/_locales/in/main.json",
    "chars": 11351,
    "preview": "{\n  \"General\": \"Umum\",\n  \"Selection Tools\": \"Alat Seleksi\",\n  \"Sites\": \"Situs\",\n  \"Advanced\": \"Lanjutan\",\n  \"Donate\": \"D"
  },
  {
    "path": "src/_locales/it/main.json",
    "chars": 11810,
    "preview": "{\n  \"General\": \"Generale\",\n  \"Selection Tools\": \"Strumenti di selezione\",\n  \"Sites\": \"Siti Web\",\n  \"Advanced\": \"Avanzato"
  },
  {
    "path": "src/_locales/ja/main.json",
    "chars": 9497,
    "preview": "{\n  \"General\": \"一般\",\n  \"Selection Tools\": \"選択ツール\",\n  \"Sites\": \"サイト適応\",\n  \"Advanced\": \"高度な\",\n  \"Donate\": \"寄付\",\n  \"Trigger"
  },
  {
    "path": "src/_locales/ko/main.json",
    "chars": 9514,
    "preview": "{\n  \"General\": \"일반\",\n  \"Selection Tools\": \"선택 도구\",\n  \"Sites\": \"사이트\",\n  \"Advanced\": \"고급\",\n  \"Donate\": \"기부\",\n  \"Triggers\":"
  },
  {
    "path": "src/_locales/pt/main.json",
    "chars": 11617,
    "preview": "{\n  \"General\": \"Geral\",\n  \"Selection Tools\": \"Ferramentas de Seleção\",\n  \"Sites\": \"Adaptação de Sites\",\n  \"Advanced\": \"A"
  },
  {
    "path": "src/_locales/resources.mjs",
    "chars": 928,
    "preview": "import de from './de/main.json'\nimport en from './en/main.json'\nimport es from './es/main.json'\nimport fr from './fr/mai"
  },
  {
    "path": "src/_locales/ru/main.json",
    "chars": 11507,
    "preview": "{\n  \"General\": \"Общие\",\n  \"Selection Tools\": \"Инструменты выбора\",\n  \"Sites\": \"Адаптация сайтов\",\n  \"Advanced\": \"Расшире"
  },
  {
    "path": "src/_locales/tr/main.json",
    "chars": 11196,
    "preview": "{\n  \"General\": \"Genel\",\n  \"Selection Tools\": \"Seçim Araçları\",\n  \"Sites\": \"Siteler\",\n  \"Advanced\": \"Gelişmiş\",\n  \"Donate"
  },
  {
    "path": "src/_locales/zh-hans/main.json",
    "chars": 9316,
    "preview": "{\n  \"General\": \"常规\",\n  \"Selection Tools\": \"选择浮动工具\",\n  \"Sites\": \"站点适配\",\n  \"Advanced\": \"高级\",\n  \"Donate\": \"打赏\",\n  \"Triggers"
  },
  {
    "path": "src/_locales/zh-hant/main.json",
    "chars": 9133,
    "preview": "{\n  \"General\": \"一般\",\n  \"Selection Tools\": \"選擇浮動工具\",\n  \"Sites\": \"網站適用\",\n  \"Advanced\": \"進階\",\n  \"Donate\": \"贊助\",\n  \"Triggers"
  },
  {
    "path": "src/background/commands.mjs",
    "chars": 787,
    "preview": "import Browser from 'webextension-polyfill'\nimport { config as menuConfig } from '../content-script/menu-tools/index.mjs"
  },
  {
    "path": "src/background/index.mjs",
    "chars": 38055,
    "preview": "import Browser from 'webextension-polyfill'\nimport {\n  deleteConversation,\n  generateAnswersWithChatgptWebApi,\n  sendMes"
  },
  {
    "path": "src/background/menus.mjs",
    "chars": 2397,
    "preview": "import Browser from 'webextension-polyfill'\nimport { defaultConfig, getPreferredLanguageKey, getUserConfig } from '../co"
  },
  {
    "path": "src/background/redact.mjs",
    "chars": 2124,
    "preview": "const SENSITIVE_KEYWORDS = [\n  'apikey', // Covers apiKey, customApiKey, claudeApiKey, etc.\n  'token', // Covers accessT"
  },
  {
    "path": "src/components/ConfirmButton/index.jsx",
    "chars": 1313,
    "preview": "import { useTranslation } from 'react-i18next'\nimport { useEffect, useRef, useState } from 'react'\nimport PropTypes from"
  },
  {
    "path": "src/components/ConversationCard/index.jsx",
    "chars": 20903,
    "preview": "import { memo, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'\nimport PropTypes from 'prop-types'\ni"
  },
  {
    "path": "src/components/ConversationItem/index.jsx",
    "chars": 4545,
    "preview": "import { memo, useState } from 'react'\nimport { ChevronDownIcon, XCircleIcon, SyncIcon } from '@primer/octicons-react'\ni"
  },
  {
    "path": "src/components/CopyButton/index.jsx",
    "chars": 918,
    "preview": "import { useState } from 'react'\nimport { CheckIcon, CopyIcon } from '@primer/octicons-react'\nimport PropTypes from 'pro"
  },
  {
    "path": "src/components/DecisionCard/index.jsx",
    "chars": 4213,
    "preview": "import { LightBulbIcon, SearchIcon } from '@primer/octicons-react'\nimport { useState, useEffect } from 'react'\nimport Pr"
  },
  {
    "path": "src/components/DeleteButton/index.jsx",
    "chars": 1418,
    "preview": "import { useEffect, useRef, useState } from 'react'\nimport PropTypes from 'prop-types'\nimport { useTranslation } from 'r"
  },
  {
    "path": "src/components/FeedbackForChatGPTWeb/index.jsx",
    "chars": 1782,
    "preview": "import PropTypes from 'prop-types'\nimport { memo, useCallback, useState } from 'react'\nimport { ThumbsupIcon, Thumbsdown"
  },
  {
    "path": "src/components/FloatingToolbar/index.jsx",
    "chars": 5638,
    "preview": "import { cloneElement, useCallback, useEffect, useState } from 'react'\nimport ConversationCard from '../ConversationCard"
  },
  {
    "path": "src/components/InputBox/index.jsx",
    "chars": 3629,
    "preview": "import { useEffect, useRef, useState } from 'react'\nimport PropTypes from 'prop-types'\nimport { isFirefox, isMobile, isS"
  },
  {
    "path": "src/components/MarkdownRender/Hyperlink.jsx",
    "chars": 1001,
    "preview": "import PropTypes from 'prop-types'\nimport Browser from 'webextension-polyfill'\n\nexport function Hyperlink({ href, childr"
  },
  {
    "path": "src/components/MarkdownRender/Pre.jsx",
    "chars": 1241,
    "preview": "import { useEffect, useRef, useState } from 'react'\nimport CopyButton from '../CopyButton'\nimport PropTypes from 'prop-t"
  },
  {
    "path": "src/components/MarkdownRender/markdown-without-katex.jsx",
    "chars": 4855,
    "preview": "import ReactMarkdown from 'react-markdown'\nimport rehypeRaw from 'rehype-raw'\nimport rehypeHighlight from 'rehype-highli"
  },
  {
    "path": "src/components/MarkdownRender/markdown.jsx",
    "chars": 4993,
    "preview": "import './mykatex.min.css'\nimport ReactMarkdown from 'react-markdown'\nimport rehypeRaw from 'rehype-raw'\nimport rehypeHi"
  },
  {
    "path": "src/components/ReadButton/index.jsx",
    "chars": 2019,
    "preview": "import { useState } from 'react'\nimport { MuteIcon, UnmuteIcon } from '@primer/octicons-react'\nimport PropTypes from 'pr"
  },
  {
    "path": "src/components/WebJumpBackNotification/index.jsx",
    "chars": 2613,
    "preview": "import { useTranslation } from 'react-i18next'\nimport PropTypes from 'prop-types'\nimport Browser from 'webextension-poly"
  },
  {
    "path": "src/components/index.mjs",
    "chars": 323,
    "preview": "export * from './ConfirmButton'\nexport * from './ConversationCard'\nexport * from './ConversationItem'\nexport * from './C"
  },
  {
    "path": "src/config/index.mjs",
    "chars": 24237,
    "preview": "import { defaults } from 'lodash-es'\nimport Browser from 'webextension-polyfill'\nimport { isMobile } from '../utils/is-m"
  },
  {
    "path": "src/config/language.mjs",
    "chars": 1145,
    "preview": "import { languages } from 'countries-list'\nimport { defaultConfig, getUserConfig } from './index.mjs'\n\nexport const lang"
  },
  {
    "path": "src/content-script/index.jsx",
    "chars": 39767,
    "preview": "import './styles.scss'\nimport { unmountComponentAtNode } from 'react-dom'\nimport { render } from 'preact'\nimport Decisio"
  },
  {
    "path": "src/content-script/menu-tools/index.mjs",
    "chars": 2679,
    "preview": "import { getCoreContentText } from '../../utils/get-core-content-text'\nimport Browser from 'webextension-polyfill'\nimpor"
  },
  {
    "path": "src/content-script/selection-tools/index.mjs",
    "chars": 3999,
    "preview": "import {\n  CardHeading,\n  CardList,\n  EmojiSmile,\n  Palette,\n  QuestionCircle,\n  Translate,\n  Braces,\n  Globe,\n  ChatTex"
  },
  {
    "path": "src/content-script/site-adapters/arxiv/index.mjs",
    "chars": 969,
    "preview": "import { cropText } from '../../../utils'\n\nexport default {\n  inputQuery: async () => {\n    try {\n      const title = do"
  },
  {
    "path": "src/content-script/site-adapters/baidu/index.mjs",
    "chars": 772,
    "preview": "import { config } from '../index'\n\nexport default {\n  init: async (hostname, userConfig, getInput, mountComponent) => {\n"
  },
  {
    "path": "src/content-script/site-adapters/bilibili/index.mjs",
    "chars": 2639,
    "preview": "import { cropText, waitForElementToExistAndSelect } from '../../../utils'\nimport { config } from '../index.mjs'\n\nexport "
  },
  {
    "path": "src/content-script/site-adapters/brave/index.mjs",
    "chars": 375,
    "preview": "import { waitForElementToExistAndSelect } from '../../../utils'\nimport { config } from '../index.mjs'\n\nexport default {\n"
  },
  {
    "path": "src/content-script/site-adapters/duckduckgo/index.mjs",
    "chars": 332,
    "preview": "import { waitForElementToExistAndSelect } from '../../../utils/index.mjs'\nimport { config } from '../index'\n\nexport defa"
  },
  {
    "path": "src/content-script/site-adapters/followin/index.mjs",
    "chars": 1440,
    "preview": "import { cropText } from '../../../utils'\n\nexport default {\n  inputQuery: async () => {\n    try {\n      const author = d"
  },
  {
    "path": "src/content-script/site-adapters/github/index.mjs",
    "chars": 6037,
    "preview": "import { cropText, limitedFetch } from '../../../utils'\nimport { config } from '../index.mjs'\n\nconst getPatchUrl = async"
  },
  {
    "path": "src/content-script/site-adapters/gitlab/index.mjs",
    "chars": 2198,
    "preview": "import { cropText, limitedFetch } from '../../../utils'\n\nconst getPatchUrl = async () => {\n  const patchUrl = location.o"
  },
  {
    "path": "src/content-script/site-adapters/index.mjs",
    "chars": 6871,
    "preview": "import baidu from './baidu'\nimport bilibili from './bilibili'\nimport youtube from './youtube'\nimport github from './gith"
  },
  {
    "path": "src/content-script/site-adapters/juejin/index.mjs",
    "chars": 1166,
    "preview": "import { cropText } from '../../../utils'\n\nexport default {\n  inputQuery: async () => {\n    try {\n      const title = do"
  },
  {
    "path": "src/content-script/site-adapters/quora/index.mjs",
    "chars": 806,
    "preview": "import { cropText } from '../../../utils'\n\nexport default {\n  inputQuery: async () => {\n    try {\n      if (location.pat"
  },
  {
    "path": "src/content-script/site-adapters/reddit/index.mjs",
    "chars": 912,
    "preview": "import { cropText } from '../../../utils'\n\nexport default {\n  inputQuery: async () => {\n    try {\n      const title = do"
  },
  {
    "path": "src/content-script/site-adapters/stackoverflow/index.mjs",
    "chars": 1503,
    "preview": "import { cropText } from '../../../utils'\n\nexport default {\n  inputQuery: async () => {\n    try {\n      const title = do"
  },
  {
    "path": "src/content-script/site-adapters/weixin/index.mjs",
    "chars": 1241,
    "preview": "import { cropText } from '../../../utils'\n\nexport default {\n  inputQuery: async () => {\n    try {\n      const title = do"
  },
  {
    "path": "src/content-script/site-adapters/youtube/index.mjs",
    "chars": 3120,
    "preview": "import { cropText } from '../../../utils'\nimport { config } from '../index.mjs'\n\n// This function was written by ChatGPT"
  },
  {
    "path": "src/content-script/site-adapters/zhihu/index.mjs",
    "chars": 2040,
    "preview": "import { cropText } from '../../../utils'\n\nexport default {\n  inputQuery: async () => {\n    try {\n      const title = do"
  },
  {
    "path": "src/content-script/styles.scss",
    "chars": 31846,
    "preview": "@import '../fonts/styles.css';\n@import '../pages/styles.scss';\n\n[data-theme='auto'] {\n  @media screen and (prefers-color"
  },
  {
    "path": "src/fonts/styles.css",
    "chars": 1940,
    "preview": "/* arabic */\n@font-face {\n  font-family: 'Cairo';\n  font-style: normal;\n  font-weight: 400;\n  font-display: swap;\n  src:"
  },
  {
    "path": "src/hooks/use-clamp-window-size.mjs",
    "chars": 374,
    "preview": "import { useWindowSize } from './use-window-size.mjs'\n\nexport function useClampWindowSize(widthRange = [0, Infinity], he"
  },
  {
    "path": "src/hooks/use-config.mjs",
    "chars": 945,
    "preview": "import { useEffect, useState } from 'react'\nimport { defaultConfig, getUserConfig } from '../config/index.mjs'\nimport Br"
  },
  {
    "path": "src/hooks/use-theme.mjs",
    "chars": 269,
    "preview": "import { useConfig } from './use-config.mjs'\nimport { useWindowTheme } from './use-window-theme.mjs'\n\nexport function us"
  },
  {
    "path": "src/hooks/use-window-size.mjs",
    "chars": 493,
    "preview": "// https://stackoverflow.com/questions/19014250/rerender-view-on-browser-resize-with-react\n\nimport { useLayoutEffect, us"
  },
  {
    "path": "src/hooks/use-window-theme.mjs",
    "chars": 628,
    "preview": "import { useEffect, useState } from 'react'\n\nexport function useWindowTheme() {\n  const [theme, setTheme] = useState(\n  "
  },
  {
    "path": "src/manifest.json",
    "chars": 2396,
    "preview": "{\n  \"name\": \"ChatGPTBox\",\n  \"description\": \"Integrating ChatGPT into your browser deeply, everything you need is here\",\n"
  },
  {
    "path": "src/manifest.v2.json",
    "chars": 1936,
    "preview": "{\n  \"name\": \"ChatGPTBox\",\n  \"description\": \"Integrating ChatGPT into your browser deeply, everything you need is here\",\n"
  },
  {
    "path": "src/pages/IndependentPanel/App.jsx",
    "chars": 6215,
    "preview": "import {\n  createSession,\n  resetSessions,\n  getSessions,\n  updateSession,\n  getSession,\n  deleteSession,\n} from '../../"
  },
  {
    "path": "src/pages/IndependentPanel/index.html",
    "chars": 398,
    "preview": "<html>\n  <head>\n    <title>ChatGPTBox</title>\n    <link rel=\"stylesheet\" href=\"content-script.css\" />\n    <meta name=\"vi"
  },
  {
    "path": "src/pages/IndependentPanel/index.jsx",
    "chars": 596,
    "preview": "import { render } from 'preact'\nimport '../../_locales/i18n-react'\nimport App from './App'\nimport Browser from 'webexten"
  },
  {
    "path": "src/pages/IndependentPanel/styles.scss",
    "chars": 2984,
    "preview": "[data-theme='auto'] {\n  @media screen and (prefers-color-scheme: dark) {\n    --font-color: #c9d1d9;\n    --font-active-co"
  },
  {
    "path": "src/pages/styles.scss",
    "chars": 40,
    "preview": "@import 'IndependentPanel/styles.scss';\n"
  },
  {
    "path": "src/popup/Popup.jsx",
    "chars": 4197,
    "preview": "import '@picocss/pico'\nimport { useEffect, useState } from 'react'\nimport {\n  defaultConfig,\n  getPreferredLanguageKey,\n"
  },
  {
    "path": "src/popup/index.html",
    "chars": 332,
    "preview": "<html>\n  <head>\n    <title>ChatGPTBox</title>\n    <link rel=\"stylesheet\" href=\"popup.css\" />\n    <meta name=\"viewport\" c"
  },
  {
    "path": "src/popup/index.jsx",
    "chars": 1146,
    "preview": "import { render } from 'preact'\nimport Popup from './Popup'\nimport '../_locales/i18n-react'\nimport { getUserConfig } fro"
  },
  {
    "path": "src/popup/sections/AdvancedPart.jsx",
    "chars": 6620,
    "preview": "import { useTranslation } from 'react-i18next'\nimport { parseFloatWithClamp, parseIntWithClamp } from '../../utils/index"
  },
  {
    "path": "src/popup/sections/ApiModes.jsx",
    "chars": 7848,
    "preview": "import { useTranslation } from 'react-i18next'\nimport PropTypes from 'prop-types'\nimport {\n  apiModeToModelName,\n  getAp"
  },
  {
    "path": "src/popup/sections/FeaturePages.jsx",
    "chars": 2891,
    "preview": "import { useTranslation } from 'react-i18next'\nimport { useState } from 'react'\nimport { isEdge, isFirefox, isMobile, is"
  },
  {
    "path": "src/popup/sections/GeneralPart.jsx",
    "chars": 19919,
    "preview": "import { useTranslation } from 'react-i18next'\nimport { useLayoutEffect, useState } from 'react'\nimport FileSaver from '"
  },
  {
    "path": "src/popup/sections/ModulesPart.jsx",
    "chars": 1126,
    "preview": "import { useTranslation } from 'react-i18next'\nimport PropTypes from 'prop-types'\nimport { Tab, TabList, TabPanel, Tabs "
  },
  {
    "path": "src/popup/sections/SelectionTools.jsx",
    "chars": 5878,
    "preview": "import { useTranslation } from 'react-i18next'\nimport { config as toolsConfig } from '../../content-script/selection-too"
  },
  {
    "path": "src/popup/sections/SiteAdapters.jsx",
    "chars": 1085,
    "preview": "import PropTypes from 'prop-types'\n\nconst siteDisplayNames = {\n  bilibili: 'Bilibili',\n  github: 'GitHub',\n  gitlab: 'Gi"
  },
  {
    "path": "src/popup/sections/import-data-cleanup.mjs",
    "chars": 996,
    "preview": "const conflictingKeyPairs = [\n  ['claudeApiKey', 'anthropicApiKey'],\n  ['customClaudeApiUrl', 'customAnthropicApiUrl'],\n"
  },
  {
    "path": "src/popup/styles.scss",
    "chars": 1597,
    "preview": "[data-theme='auto'] {\n  @media screen and (prefers-color-scheme: dark) {\n    --font-color: #c9d1d9;\n    --theme-color: #"
  },
  {
    "path": "src/rules.json",
    "chars": 1458,
    "preview": "[\n  {\n    \"id\": 1,\n    \"action\": {\n      \"type\": \"modifyHeaders\",\n      \"requestHeaders\": [\n        {\n          \"operati"
  },
  {
    "path": "src/services/apis/aiml-api.mjs",
    "chars": 418,
    "preview": "import { generateAnswersWithOpenAiApiCompat } from './openai-api.mjs'\n\n/**\n * @param {Browser.Runtime.Port} port\n * @par"
  },
  {
    "path": "src/services/apis/azure-openai-api.mjs",
    "chars": 2948,
    "preview": "import { getUserConfig } from '../../config/index.mjs'\nimport { pushRecord, setAbortController } from './shared.mjs'\nimp"
  },
  {
    "path": "src/services/apis/bard-web.mjs",
    "chars": 1062,
    "preview": "import { pushRecord } from './shared.mjs'\nimport Bard from '../clients/bard'\n\n/**\n * @param {Runtime.Port} port\n * @para"
  },
  {
    "path": "src/services/apis/bing-web.mjs",
    "chars": 3409,
    "preview": "import BingAIClient from '../clients/bing/index.mjs'\nimport { getUserConfig } from '../../config/index.mjs'\nimport { pus"
  },
  {
    "path": "src/services/apis/chatglm-api.mjs",
    "chars": 563,
    "preview": "import { getUserConfig } from '../../config/index.mjs'\n// import { getToken } from '../../utils/jwt-token-generator.mjs'"
  },
  {
    "path": "src/services/apis/chatgpt-web.mjs",
    "chars": 14099,
    "preview": "// web version\n\nimport { fetchSSE } from '../../utils/fetch-sse.mjs'\nimport { isEmpty } from 'lodash-es'\nimport { getUse"
  },
  {
    "path": "src/services/apis/claude-api.mjs",
    "chars": 2637,
    "preview": "import { getUserConfig } from '../../config/index.mjs'\nimport { pushRecord, setAbortController } from './shared.mjs'\nimp"
  },
  {
    "path": "src/services/apis/claude-web.mjs",
    "chars": 1730,
    "preview": "import { pushRecord, setAbortController } from './shared.mjs'\nimport Claude from '../clients/claude'\nimport { getModelVa"
  },
  {
    "path": "src/services/apis/custom-api.mjs",
    "chars": 3431,
    "preview": "// custom api version\n\n// There is a lot of duplicated code here, but it is very easy to refactor.\n// The current state "
  },
  {
    "path": "src/services/apis/deepseek-api.mjs",
    "chars": 420,
    "preview": "import { generateAnswersWithOpenAiApiCompat } from './openai-api.mjs'\n\n/**\n * @param {Browser.Runtime.Port} port\n * @par"
  },
  {
    "path": "src/services/apis/moonshot-api.mjs",
    "chars": 432,
    "preview": "import { generateAnswersWithOpenAiApiCompat } from './openai-api.mjs'\n\n/**\n * @param {Browser.Runtime.Port} port\n * @par"
  },
  {
    "path": "src/services/apis/moonshot-web.mjs",
    "chars": 18157,
    "preview": "import { pushRecord, setAbortController } from './shared.mjs'\nimport { setUserConfig } from '../../config/index.mjs'\nimp"
  },
  {
    "path": "src/services/apis/ollama-api.mjs",
    "chars": 1045,
    "preview": "import { getUserConfig } from '../../config/index.mjs'\nimport { generateAnswersWithOpenAiApiCompat } from './openai-api."
  },
  {
    "path": "src/services/apis/openai-api.mjs",
    "chars": 6218,
    "preview": "// api version\n\nimport { getUserConfig } from '../../config/index.mjs'\nimport { fetchSSE } from '../../utils/fetch-sse.m"
  },
  {
    "path": "src/services/apis/openai-token-params.mjs",
    "chars": 684,
    "preview": "const GPT5_CHAT_COMPLETIONS_MODEL_PATTERN = /^gpt-5([.-]|$)/\n\nfunction shouldUseMaxCompletionTokens(provider, model) {\n "
  },
  {
    "path": "src/services/apis/openrouter-api.mjs",
    "chars": 426,
    "preview": "import { generateAnswersWithOpenAiApiCompat } from './openai-api.mjs'\n\n/**\n * @param {Browser.Runtime.Port} port\n * @par"
  },
  {
    "path": "src/services/apis/poe-web.mjs",
    "chars": 1412,
    "preview": "import { pushRecord, setAbortController } from './shared.mjs'\nimport PoeAiClient from '../clients/poe/index.mjs'\n\n/**\n *"
  },
  {
    "path": "src/services/apis/shared.mjs",
    "chars": 2069,
    "preview": "export const getChatSystemPromptBase = async () => {\n  return `You are a helpful, creative, clever, and very friendly as"
  },
  {
    "path": "src/services/apis/waylaidwanderer-api.mjs",
    "chars": 2955,
    "preview": "import { pushRecord, setAbortController } from './shared.mjs'\nimport { getUserConfig } from '../../config/index.mjs'\nimp"
  },
  {
    "path": "src/services/clients/bard/index.mjs",
    "chars": 4474,
    "preview": "// https://github.com/PawanOsman/GoogleBard\n\nexport default class Bard {\n  cookies = ''\n\n  constructor(cookies) {\n    th"
  },
  {
    "path": "src/services/clients/bing/BingImageCreator.js",
    "chars": 20416,
    "preview": "export default class BingImageCreator {\n  /**\n   * @constructor\n   * @param {Object} options - Options for BingImageCrea"
  },
  {
    "path": "src/services/clients/bing/index.mjs",
    "chars": 23005,
    "preview": "// https://github.com/waylaidwanderer/node-chatgpt-api\n\nimport { v4 as uuidv4 } from 'uuid'\n// import BingImageCreator f"
  },
  {
    "path": "src/services/clients/claude/index.mjs",
    "chars": 29815,
    "preview": "// https://github.com/Explosion-Scratch/claude-unofficial-api\n/* eslint-disable */\n\nimport { fetchSSE } from '../../../u"
  },
  {
    "path": "src/services/clients/poe/graphql/AddHumanMessageMutation.graphql",
    "chars": 1093,
    "preview": "mutation AddHumanMessageMutation(\n    $chatId: BigInt!\n    $bot: String!\n    $query: String!\n    $source: MessageSource\n"
  },
  {
    "path": "src/services/clients/poe/graphql/AddMessageBreakMutation.graphql",
    "chars": 373,
    "preview": "mutation AddMessageBreakMutation($chatId: BigInt!) {\n    messageBreakCreate(chatId: $chatId) {\n        message {\n       "
  },
  {
    "path": "src/services/clients/poe/graphql/AutoSubscriptionMutation.graphql",
    "chars": 180,
    "preview": "mutation AutoSubscriptionMutation($subscriptions: [AutoSubscriptionQuery!]!) {\n    autoSubscribe(subscriptions: $subscri"
  },
  {
    "path": "src/services/clients/poe/graphql/BioFragment.graphql",
    "chars": 97,
    "preview": "fragment BioFragment on Viewer {\n    id\n    poeUser {\n        id\n        uid\n        bio\n    }\n}\n"
  },
  {
    "path": "src/services/clients/poe/graphql/ChatAddedSubscription.graphql",
    "chars": 73,
    "preview": "subscription ChatAddedSubscription {\n\tchatAdded {\n\t\t...ChatFragment\n\t}\n}\n"
  },
  {
    "path": "src/services/clients/poe/graphql/ChatFragment.graphql",
    "chars": 100,
    "preview": "fragment ChatFragment on Chat {\n    id\n    chatId\n    defaultBotNickname\n    shouldShowDisclaimer\n}\n"
  },
  {
    "path": "src/services/clients/poe/graphql/ChatPaginationQuery.graphql",
    "chars": 686,
    "preview": "query ChatPaginationQuery($bot: String!, $before: String, $last: Int! = 10) {\n    chatOfBot(bot: $bot) {\n        id\n    "
  },
  {
    "path": "src/services/clients/poe/graphql/ChatViewQuery.graphql",
    "chars": 154,
    "preview": "query ChatViewQuery($bot: String!) {\n    chatOfBot(bot: $bot) {\n        id\n        chatId\n        defaultBotNickname\n   "
  },
  {
    "path": "src/services/clients/poe/graphql/DeleteHumanMessagesMutation.graphql",
    "chars": 160,
    "preview": "mutation DeleteHumanMessagesMutation($messageIds: [BigInt!]!) {\n    messagesDelete(messageIds: $messageIds) {\n        vi"
  },
  {
    "path": "src/services/clients/poe/graphql/HandleFragment.graphql",
    "chars": 103,
    "preview": "fragment HandleFragment on Viewer {\n    id\n    poeUser {\n        id\n        uid\n        handle\n    }\n}\n"
  },
  {
    "path": "src/services/clients/poe/graphql/LoginWithVerificationCodeMutation.graphql",
    "chars": 306,
    "preview": "mutation LoginWithVerificationCodeMutation(\n    $verificationCode: String!\n    $emailAddress: String\n    $phoneNumber: S"
  },
  {
    "path": "src/services/clients/poe/graphql/MessageAddedSubscription.graphql",
    "chars": 117,
    "preview": "subscription MessageAddedSubscription($chatId: BigInt!) {\n\tmessageAdded(chatId: $chatId) {\n\t\t...MessageFragment\n\t}\n}\n"
  },
  {
    "path": "src/services/clients/poe/graphql/MessageDeletedSubscription.graphql",
    "chars": 135,
    "preview": "subscription MessageDeletedSubscription($chatId: BigInt!) {\n    messageDeleted(chatId: $chatId) {\n        id\n        mes"
  },
  {
    "path": "src/services/clients/poe/graphql/MessageFragment.graphql",
    "chars": 194,
    "preview": "fragment MessageFragment on Message {\n    id\n    __typename\n    messageId\n    text\n    linkifiedText\n    authorNickname\n"
  },
  {
    "path": "src/services/clients/poe/graphql/MessageRemoveVoteMutation.graphql",
    "chars": 145,
    "preview": "mutation MessageRemoveVoteMutation($messageId: BigInt!) {\n\tmessageRemoveVote(messageId: $messageId) {\n\t\tmessage {\n\t\t\t..."
  },
  {
    "path": "src/services/clients/poe/graphql/MessageSetVoteMutation.graphql",
    "chars": 216,
    "preview": "mutation MessageSetVoteMutation($messageId: BigInt!, $voteType: VoteType!, $reason: String) {\n\tmessageSetVote(messageId:"
  },
  {
    "path": "src/services/clients/poe/graphql/SendVerificationCodeForLoginMutation.graphql",
    "chars": 263,
    "preview": "mutation SendVerificationCodeForLoginMutation(\n    $emailAddress: String\n    $phoneNumber: String\n) {\n    sendVerificati"
  },
  {
    "path": "src/services/clients/poe/graphql/ShareMessagesMutation.graphql",
    "chars": 213,
    "preview": "mutation ShareMessagesMutation(\n    $chatId: BigInt!\n    $messageIds: [BigInt!]!\n    $comment: String\n) {\n    messagesSh"
  },
  {
    "path": "src/services/clients/poe/graphql/SignupWithVerificationCodeMutation.graphql",
    "chars": 308,
    "preview": "mutation SignupWithVerificationCodeMutation(\n    $verificationCode: String!\n    $emailAddress: String\n    $phoneNumber: "
  },
  {
    "path": "src/services/clients/poe/graphql/StaleChatUpdateMutation.graphql",
    "chars": 159,
    "preview": "mutation StaleChatUpdateMutation($chatId: BigInt!) {\n    staleChatUpdate(chatId: $chatId) {\n        message {\n          "
  },
  {
    "path": "src/services/clients/poe/graphql/SummarizePlainPostQuery.graphql",
    "chars": 95,
    "preview": "query SummarizePlainPostQuery($comment: String!) {\n    summarizePlainPost(comment: $comment)\n}\n"
  },
  {
    "path": "src/services/clients/poe/graphql/SummarizeQuotePostQuery.graphql",
    "chars": 147,
    "preview": "query SummarizeQuotePostQuery($comment: String, $quotedPostId: BigInt!) {\n    summarizeQuotePost(comment: $comment, quot"
  },
  {
    "path": "src/services/clients/poe/graphql/SummarizeSharePostQuery.graphql",
    "chars": 180,
    "preview": "query SummarizeSharePostQuery($comment: String!, $chatId: BigInt!, $messageIds: [BigInt!]!) {\n    summarizeSharePost(com"
  },
  {
    "path": "src/services/clients/poe/graphql/UserSnippetFragment.graphql",
    "chars": 368,
    "preview": "fragment UserSnippetFragment on PoeUser {\n    id\n    uid\n    bio\n    handle\n    fullName\n    viewerIsFollowing\n    isPoe"
  },
  {
    "path": "src/services/clients/poe/graphql/ViewerInfoQuery.graphql",
    "chars": 400,
    "preview": "query ViewerInfoQuery {\n    viewer {\n        id\n        uid\n        ...ViewerStateFragment\n        ...BioFragment\n      "
  },
  {
    "path": "src/services/clients/poe/graphql/ViewerStateFragment.graphql",
    "chars": 1038,
    "preview": "fragment ViewerStateFragment on Viewer {\n    id\n    __typename\n    iosMinSupportedVersion: integerGate(gateName: \"poe_io"
  },
  {
    "path": "src/services/clients/poe/graphql/ViewerStateUpdatedSubscription.graphql",
    "chars": 110,
    "preview": "subscription ViewerStateUpdatedSubscription {\n    viewerStateUpdated {\n        ...ViewerStateFragment\n    }\n}\n"
  },
  {
    "path": "src/services/clients/poe/index.mjs",
    "chars": 7414,
    "preview": "// reference: https://github.com/muharamdani/poe\n\nimport { connectWs, disconnectWs, listenWs } from './websocket.js'\nimp"
  },
  {
    "path": "src/services/clients/poe/websocket.js",
    "chars": 2040,
    "preview": "import * as diff from 'diff'\n\nconst getSocketUrl = async (settings) => {\n  settings = settings.tchannelData\n  const tchR"
  },
  {
    "path": "src/services/init-session.mjs",
    "chars": 2906,
    "preview": "import { v4 as uuidv4 } from 'uuid'\nimport { apiModeToModelName, modelNameToDesc } from '../utils/model-name-convert.mjs"
  },
  {
    "path": "src/services/local-session.mjs",
    "chars": 2452,
    "preview": "import Browser from 'webextension-polyfill'\nimport { initSession } from './init-session.mjs'\nimport { getUserConfig } fr"
  },
  {
    "path": "src/services/wrappers.mjs",
    "chars": 4636,
    "preview": "import {\n  clearOldAccessToken,\n  getUserConfig,\n  isUsingBingWebModel,\n  isUsingClaudeWebModel,\n  setAccessToken,\n} fro"
  },
  {
    "path": "src/utils/change-children-font-size.mjs",
    "chars": 248,
    "preview": "export function changeChildrenFontSize(element, size) {\n  try {\n    element.style.fontSize = size\n  } catch {\n    /* emp"
  },
  {
    "path": "src/utils/create-element-at-position.mjs",
    "chars": 322,
    "preview": "export function createElementAtPosition(x = 0, y = 0, zIndex = 2147483647) {\n  const element = document.createElement('d"
  },
  {
    "path": "src/utils/crop-text.mjs",
    "chars": 3779,
    "preview": "// MIT License\n//\n// Copyright (c) 2023 josStorer\n//\n// Permission is hereby granted, free of charge, to any person obta"
  },
  {
    "path": "src/utils/ends-with-question-mark.mjs",
    "chars": 232,
    "preview": "export function endsWithQuestionMark(question) {\n  return (\n    question.endsWith('?') || // ASCII\n    question.endsWith"
  },
  {
    "path": "src/utils/eventsource-parser.mjs",
    "chars": 3780,
    "preview": "// https://www.npmjs.com/package/eventsource-parser/v/1.1.1\n\nfunction createParser(onParse) {\n  let isFirstChunk\n  let b"
  },
  {
    "path": "src/utils/fetch-bg.mjs",
    "chars": 818,
    "preview": "import Browser from 'webextension-polyfill'\n\n/**\n * @param {RequestInfo|URL} input\n * @param {RequestInit=} init\n * @ret"
  },
  {
    "path": "src/utils/fetch-sse.mjs",
    "chars": 1169,
    "preview": "import { createParser } from './eventsource-parser.mjs'\n\nexport async function fetchSSE(resource, options) {\n  const { o"
  },
  {
    "path": "src/utils/get-client-position.mjs",
    "chars": 121,
    "preview": "export function getClientPosition(e) {\n  const rect = e.getBoundingClientRect()\n  return { x: rect.left, y: rect.top }\n}"
  },
  {
    "path": "src/utils/get-conversation-pairs.mjs",
    "chars": 451,
    "preview": "export function getConversationPairs(records, isCompletion) {\n  let pairs\n  if (isCompletion) {\n    pairs = ''\n    for ("
  },
  {
    "path": "src/utils/get-core-content-text.mjs",
    "chars": 2687,
    "preview": "import { getPossibleElementByQuerySelector } from './get-possible-element-by-query-selector.mjs'\nimport { Readability, i"
  },
  {
    "path": "src/utils/get-possible-element-by-query-selector.mjs",
    "chars": 327,
    "preview": "export function getPossibleElementByQuerySelector(queryArray) {\n  if (!queryArray) return\n  for (const query of queryArr"
  },
  {
    "path": "src/utils/index.mjs",
    "chars": 841,
    "preview": "export * from './change-children-font-size'\nexport * from './create-element-at-position'\nexport * from './crop-text'\nexp"
  },
  {
    "path": "src/utils/is-edge.mjs",
    "chars": 88,
    "preview": "export function isEdge() {\n  return navigator.userAgent.toLowerCase().includes('edg')\n}\n"
  },
  {
    "path": "src/utils/is-firefox.mjs",
    "chars": 95,
    "preview": "export function isFirefox() {\n  return navigator.userAgent.toLowerCase().includes('firefox')\n}\n"
  },
  {
    "path": "src/utils/is-mobile.mjs",
    "chars": 2329,
    "preview": "// https://stackoverflow.com/questions/11381673/detecting-a-mobile-browser\n\nexport function isMobile() {\n  if (navigator"
  },
  {
    "path": "src/utils/is-safari.mjs",
    "chars": 84,
    "preview": "export function isSafari() {\n  return navigator.vendor === 'Apple Computer, Inc.'\n}\n"
  },
  {
    "path": "src/utils/jwt-token-generator.mjs",
    "chars": 975,
    "preview": "import jwt from 'jsonwebtoken'\n\nlet jwtToken = null\nlet tokenExpiration = null // Declare tokenExpiration in the module "
  },
  {
    "path": "src/utils/limited-fetch.mjs",
    "chars": 676,
    "preview": "// https://stackoverflow.com/questions/64304365/stop-request-after-x-amount-is-fetched\n\nexport async function limitedFet"
  },
  {
    "path": "src/utils/model-name-convert.mjs",
    "chars": 5585,
    "preview": "import { AlwaysCustomGroups, ModelGroups, ModelMode, Models } from '../config/index.mjs'\n\nexport function modelNameToDes"
  },
  {
    "path": "src/utils/open-url.mjs",
    "chars": 288,
    "preview": "import Browser from 'webextension-polyfill'\n\nexport function openUrl(url) {\n  Browser.tabs.query({ url, currentWindow: t"
  },
  {
    "path": "src/utils/parse-float-with-clamp.mjs",
    "chars": 229,
    "preview": "export function parseFloatWithClamp(value, defaultValue, min, max) {\n  value = parseFloat(value)\n\n  if (isNaN(value)) va"
  },
  {
    "path": "src/utils/parse-int-with-clamp.mjs",
    "chars": 225,
    "preview": "export function parseIntWithClamp(value, defaultValue, min, max) {\n  value = parseInt(value)\n\n  if (isNaN(value)) value "
  },
  {
    "path": "src/utils/set-element-position-in-viewport.mjs",
    "chars": 361,
    "preview": "export function setElementPositionInViewport(element, x = 0, y = 0) {\n  const retX = Math.min(Math.max(0, window.innerWi"
  },
  {
    "path": "src/utils/update-ref-height.mjs",
    "chars": 482,
    "preview": "export function updateRefHeight(ref) {\n  ref.current.style.height = 'auto'\n  const computed = window.getComputedStyle(re"
  },
  {
    "path": "src/utils/wait-for-element-to-exist-and-select.mjs",
    "chars": 615,
    "preview": "export function waitForElementToExistAndSelect(selector, timeout = 0) {\n  return new Promise((resolve) => {\n    if (docu"
  },
  {
    "path": "tests/setup/browser-shim.mjs",
    "chars": 4956,
    "preview": "// Minimal browser-extension API shim for Node test runtime.\n// Scope is intentionally small: only APIs used by current "
  },
  {
    "path": "tests/setup/jsx-loader-hooks.mjs",
    "chars": 2220,
    "preview": "// ESM loader hooks that transform .mjs files containing JSX via esbuild\n// and provide CJS-to-ESM interop for packages "
  },
  {
    "path": "tests/unit/background/redact.test.mjs",
    "chars": 3841,
    "preview": "import assert from 'node:assert/strict'\nimport { describe, test } from 'node:test'\nimport {\n  redactSensitiveFields,\n  i"
  }
]

// ... and 27 more files (download for full content)

About this extraction

This page contains the full source code of the ChatGPTBox-dev/chatGPTBox GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 227 files (910.5 KB), approximately 252.9k tokens, and a symbol index with 350 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!