├── .github ├── ISSUE_TEMPLATE │ ├── bug-report---bug-报告.md │ └── feature-request---新功能建议.md └── workflows │ ├── codeql.yml │ └── docker-image.yml ├── .gitignore ├── .gitmodules ├── Caddyfile ├── Dockerfile ├── LICENSE ├── README.en.md ├── README.md ├── backend ├── .gitignore ├── alembic.ini ├── alembic │ ├── README │ ├── env.py │ ├── script.py.mako │ └── versions │ │ ├── 0d790c2c26dc_add_uploaded_files_table.py │ │ ├── 333722b0921e_add_source_id_for_baseconversation.py │ │ ├── 7d94b5503088_add_extra_info_in_uploadedfileinfo.py │ │ └── aa3d85891014_baseline.py ├── api │ ├── __init__.py │ ├── conf │ │ ├── __init__.py │ │ ├── base_config.py │ │ ├── config.py │ │ └── credentials.py │ ├── database │ │ ├── __init__.py │ │ ├── custom_types │ │ │ ├── __init__.py │ │ │ ├── guid.py │ │ │ ├── pydantic_type.py │ │ │ └── utc_datetime.py │ │ ├── mongodb.py │ │ └── sqlalchemy.py │ ├── enums │ │ ├── __init__.py │ │ ├── models.py │ │ ├── options.py │ │ └── status.py │ ├── exceptions.py │ ├── file_provider.py │ ├── globals.py │ ├── middlewares │ │ ├── __init__.py │ │ ├── asgi_logger │ │ │ ├── __init__.py │ │ │ ├── middleware.py │ │ │ └── utils.py │ │ └── request_statistics.py │ ├── models │ │ ├── __init__.py │ │ ├── db.py │ │ ├── doc │ │ │ ├── __init__.py │ │ │ └── openai_web_code_interpreter.py │ │ ├── json.py │ │ └── types.py │ ├── response.py │ ├── routers │ │ ├── __init__.py │ │ ├── arkose.py │ │ ├── chat.py │ │ ├── conv.py │ │ ├── files.py │ │ ├── logs.py │ │ ├── status.py │ │ ├── system.py │ │ └── users.py │ ├── schemas │ │ ├── __init__.py │ │ ├── conversation_schemas.py │ │ ├── file_schemas.py │ │ ├── openai_schemas.py │ │ ├── status_schemas.py │ │ ├── system_schemas.py │ │ └── user_schemas.py │ ├── sources │ │ ├── __init__.py │ │ ├── openai_api.py │ │ └── openai_web.py │ └── users.py ├── config_templates │ ├── config.yaml │ └── credentials.yaml ├── logging_config.yaml ├── main.py ├── manage.py ├── poetry.lock ├── pyproject.toml ├── requirements.txt └── utils │ ├── __init__.py │ ├── admin │ ├── __init__.py │ └── sync_conv.py │ ├── common.py │ └── logger.py ├── docs ├── donate.png ├── screenshot.en.jpeg ├── screenshot.jpeg └── screenshot_admin.jpeg ├── frontend ├── .env ├── .eslintignore ├── .eslintrc.cjs ├── .gitignore ├── .prettierrc.cjs ├── .vscode │ ├── extensions.json │ ├── launch.json │ └── settings.json ├── components.d.ts ├── config │ ├── utils │ │ └── icon-component-resolver.ts │ ├── vite.config.base.ts │ ├── vite.config.dev.ts │ └── vite.config.prod.ts ├── index.html ├── package.json ├── pnpm-lock.yaml ├── public │ ├── chatgpt-icon-black.svg │ ├── chatgpt-icon.svg │ ├── icon.png │ └── icon.svg ├── scripts │ ├── dereference_openapi.js │ └── updateapi.sh ├── src │ ├── App.vue │ ├── api │ │ ├── arkose.ts │ │ ├── chat.ts │ │ ├── conv.ts │ │ ├── files.ts │ │ ├── interceptor.ts │ │ ├── logs.ts │ │ ├── status.ts │ │ ├── system.ts │ │ ├── url.ts │ │ └── user.ts │ ├── components │ │ ├── BrowsingIcon.vue │ │ ├── ChatGPTAvatar.vue │ │ ├── ChatGPTIcon.vue │ │ ├── ChatModelTagsRow.vue │ │ ├── ChatTypeTagInfoCell.vue │ │ ├── HelpTooltip.vue │ │ ├── OpenaiWebPluginDetailCard.vue │ │ ├── PageHeader.vue │ │ ├── PreferenceForm.vue │ │ ├── UserProfileCard.vue │ │ └── icons │ │ │ ├── CWSIcon.vue │ │ │ └── browsing │ │ │ ├── click.svg │ │ │ ├── click_result.svg │ │ │ ├── external_link.svg │ │ │ ├── failed.svg │ │ │ ├── finished.svg │ │ │ ├── go_back.svg │ │ │ ├── scroll.svg │ │ │ └── search.svg │ ├── hooks │ │ └── drawer.ts │ ├── i18n.ts │ ├── locales │ │ ├── en-US.json │ │ ├── ms-MY.json │ │ └── zh-CN.json │ ├── main.ts │ ├── router │ │ ├── guard │ │ │ ├── index.ts │ │ │ ├── permission.ts │ │ │ └── userLoginInfo.ts │ │ ├── index.ts │ │ └── typings.d.ts │ ├── store │ │ ├── index.ts │ │ ├── modules │ │ │ ├── app.ts │ │ │ ├── conversation.ts │ │ │ ├── file.ts │ │ │ └── user.ts │ │ └── types.ts │ ├── style.css │ ├── types │ │ ├── custom.ts │ │ ├── echarts.ts │ │ ├── json │ │ │ ├── config_schema.json │ │ │ ├── credentials_schema.json │ │ │ ├── model_definitions.json │ │ │ ├── openapi.json │ │ │ └── schemas.json │ │ ├── json_schema.ts │ │ ├── openapi.ts │ │ └── schema.ts │ ├── utils │ │ ├── arkose.ts │ │ ├── auth.ts │ │ ├── chat.ts │ │ ├── cookies.ts │ │ ├── highlight.ts │ │ ├── json_schema.ts │ │ ├── loading.ts │ │ ├── markdown-it-katex.ts │ │ ├── markdown.ts │ │ ├── media.ts │ │ ├── renders.ts │ │ ├── table.ts │ │ ├── time.ts │ │ ├── tips.ts │ │ ├── user.ts │ │ └── validate.ts │ ├── views │ │ ├── admin │ │ │ ├── components │ │ │ │ ├── CompletionLogContent.vue │ │ │ │ ├── CreateUserForm.vue │ │ │ │ ├── OpenaiWebPluginSetting.vue │ │ │ │ ├── ServerLogContent.vue │ │ │ │ ├── StatisticsCard.vue │ │ │ │ ├── SystemInfoCard.vue │ │ │ │ ├── UpdateChatSourceSettingForm.vue │ │ │ │ ├── UpdateUserBasicForm.vue │ │ │ │ ├── UpdateUserSettingForm.vue │ │ │ │ ├── UserSelector.vue │ │ │ │ ├── charts │ │ │ │ │ ├── AskChart.vue │ │ │ │ │ ├── RequestsChart.vue │ │ │ │ │ ├── UserUsageChart.vue │ │ │ │ │ └── helpers.ts │ │ │ │ └── inputs │ │ │ │ │ ├── CountNumberInput.vue │ │ │ │ │ ├── CountNumberInputWithAdd.vue │ │ │ │ │ ├── ModelDictField.vue │ │ │ │ │ ├── RateLimitsArrayInput.vue │ │ │ │ │ ├── TimeSlotsArrayInput.vue │ │ │ │ │ └── ValidDateTimeInput.vue │ │ │ ├── index.vue │ │ │ └── pages │ │ │ │ ├── config_manager.vue │ │ │ │ ├── conversation_manager.vue │ │ │ │ ├── log_viewer.vue │ │ │ │ ├── openai_settings.vue │ │ │ │ ├── system_manager.vue │ │ │ │ └── user_manager.vue │ │ ├── conversation │ │ │ ├── components │ │ │ │ ├── FileUploadRegion.vue │ │ │ │ ├── HistoryContent.vue │ │ │ │ ├── InputRegion.vue │ │ │ │ ├── LeftBar.vue │ │ │ │ ├── LeftBarConversationMenuLabel.vue │ │ │ │ ├── MessageRow.vue │ │ │ │ ├── MessageRowAttachmentDisplay.vue │ │ │ │ ├── MessageRowBrowserDisplay.vue │ │ │ │ ├── MessageRowCodeDisplay.vue │ │ │ │ ├── MessageRowDallePromptDisplay.vue │ │ │ │ ├── MessageRowMultimodalTextDalleDisplay.vue │ │ │ │ ├── MessageRowMultimodalTextDisplay.vue │ │ │ │ ├── MessageRowMyFilesBrowserDisplay.vue │ │ │ │ ├── MessageRowPluginAction.vue │ │ │ │ ├── MessageRowPluginDisplay.vue │ │ │ │ ├── MessageRowTextDisplay.vue │ │ │ │ ├── NewConversationForm.vue │ │ │ │ ├── NewConversationFormModelSelectionLabel.vue │ │ │ │ ├── NewConversationFormPluginSelectionLabel.vue │ │ │ │ └── StatusCard.vue │ │ │ ├── history-viewer.vue │ │ │ ├── index.vue │ │ │ └── utils │ │ │ │ ├── codeblock.ts │ │ │ │ ├── export.ts │ │ │ │ ├── files.ts │ │ │ │ └── message.ts │ │ ├── error │ │ │ ├── 403.vue │ │ │ └── 404.vue │ │ ├── home.vue │ │ ├── login │ │ │ └── index.vue │ │ └── redirect │ │ │ └── index.vue │ ├── vite-env.d.ts │ └── vue3-json-viewer.d.ts ├── tsconfig.json └── tsconfig.node.json └── startup.sh /.github/ISSUE_TEMPLATE/bug-report---bug-报告.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report / bug 报告 3 | about: 注意:配置问题请到 Discussions 区提问。请仅在确信这是一个来自代码的 bug 时使用此模板。 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Version** 11 | v0.x.x 12 | 13 | **What's your deploying method?** 14 | - [ ] Docker 15 | - [ ] Caddy 16 | - [ ] Other 17 | 18 | **Describe the bug** 19 | A clear and concise description of what the bug is. 20 | 21 | **To Reproduce** 22 | Steps to reproduce the behavior: 23 | 1. Go to '...' 24 | 2. Click on '....' 25 | 3. Scroll down to '....' 26 | 4. See error 27 | 28 | **Expected behavior** 29 | A clear and concise description of what you expected to happen. 30 | 31 | **Your config.yaml or other configurations** 32 | Provide your configurations. You may hide your secrets or access tokens. 33 | 34 | **Screenshots or running logs** 35 | If applicable, add screenshots or logs to help explain your problem. 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request---新功能建议.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request / 新功能建议 3 | about: 提建议前请先确认是否已经存在类似的 issue 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "main" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "main" ] 20 | 21 | jobs: 22 | analyze: 23 | name: Analyze 24 | runs-on: ubuntu-latest 25 | permissions: 26 | actions: read 27 | contents: read 28 | security-events: write 29 | 30 | strategy: 31 | fail-fast: false 32 | matrix: 33 | language: [ 'python' ] 34 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 35 | # Use only 'java' to analyze code written in Java, Kotlin or both 36 | # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v2 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v2 73 | with: 74 | category: "/language:${{matrix.language}}" 75 | -------------------------------------------------------------------------------- /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Build and publish Docker image 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | version: 7 | description: "Version tag for the Docker image (semver)" 8 | required: true 9 | branch: 10 | description: "Branch to build from" 11 | required: false 12 | default: 'dev' 13 | 14 | env: 15 | IMAGE_NAME: ${{ github.repository }} 16 | VERSION: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version || github.ref_name }} 17 | 18 | jobs: 19 | build-and-push-x64-image: 20 | runs-on: ubuntu-latest 21 | permissions: 22 | contents: read 23 | packages: write 24 | 25 | steps: 26 | - name: Checkout repository 27 | uses: actions/checkout@v3 28 | with: 29 | ref: ${{ github.event.inputs.branch }} 30 | 31 | # Documentation: https://github.com/docker/setup-qemu-action 32 | - name: Set up QEMU 33 | uses: docker/setup-qemu-action@v2 34 | 35 | - name: Docker meta 36 | id: meta 37 | uses: docker/metadata-action@v4 38 | with: 39 | images: | 40 | ghcr.io/${{ env.IMAGE_NAME }} 41 | ${{ env.IMAGE_NAME }} 42 | tags: | 43 | type=semver,pattern={{version}}${{ github.event_name == 'workflow_dispatch' && format(',value={0}', github.event.inputs.version) || '' }} 44 | type=semver,pattern={{major}}.{{minor}}${{ github.event_name == 'workflow_dispatch' && format(',value={0}', github.event.inputs.version) || '' }} 45 | 46 | # - name: Create Sentry release 47 | # uses: getsentry/action-release@v1 48 | # env: 49 | # SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} 50 | # SENTRY_ORG: ${{ secrets.SENTRY_ORG }} 51 | # SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} 52 | # # SENTRY_URL: https://sentry.io/ 53 | # with: 54 | # environment: production 55 | # sourcemaps: frontend/dist/assets 56 | # version: ${{ github.ref }} 57 | 58 | - name: Set up Docker Buildx 59 | uses: docker/setup-buildx-action@v2 60 | 61 | - name: Log in to the Container registry 62 | uses: docker/login-action@v2 63 | with: 64 | registry: ghcr.io 65 | username: ${{ github.actor }} 66 | password: ${{ secrets.GITHUB_TOKEN }} 67 | 68 | - name: Log in to Dockerhub 69 | uses: docker/login-action@v2 70 | with: 71 | username: ${{ github.actor }} 72 | password: ${{ secrets.DOCKERHUB_TOKEN }} 73 | 74 | - name: Build and push Docker image 75 | uses: docker/build-push-action@v4 76 | with: 77 | context: . 78 | platforms: linux/amd64,linux/arm64 79 | push: true 80 | tags: ${{ steps.meta.outputs.tags }} 81 | labels: ${{ steps.meta.outputs.labels }} 82 | cache-from: type=gha 83 | cache-to: type=gha,mode=max -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | docker/ 2 | .DS_Store -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxduke/chatgpt-web-share/2d52c390be890c0c94203ef95fb72ba3e83add0b/.gitmodules -------------------------------------------------------------------------------- /Caddyfile: -------------------------------------------------------------------------------- 1 | :80 { 2 | encode gzip 3 | 4 | @cache { 5 | path *.ico *.css *.js *.gif *.webp *.avif *.jpg *.jpeg *.png *.svg *.woff *.woff2 *.html *.ttf *.eot 6 | } 7 | header @cache Cache-Control "public, max-age=604800, must-revalidate" 8 | 9 | handle_path /api/* { 10 | reverse_proxy localhost:8000 11 | } 12 | handle /* { 13 | file_server 14 | root * /app/dist 15 | try_files {path} /index.html 16 | } 17 | } 18 | 19 | # example for subdirectory deploy: 20 | 21 | # :7777 { 22 | # handle_path /chat/api/* { 23 | # uri strip_prefix /chat 24 | # reverse_proxy :8000 25 | # } 26 | # handle_path /chat/* { 27 | # file_server 28 | # root * ./frontend/dist 29 | # try_files {path} /index.html 30 | # } 31 | # } 32 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:18-alpine AS FrontendBuilder 2 | 3 | WORKDIR /app 4 | RUN npm install pnpm -g 5 | COPY frontend/package*.json ./frontend/ 6 | 7 | WORKDIR /app/frontend 8 | RUN pnpm install 9 | COPY frontend ./ 10 | RUN pnpm build 11 | 12 | FROM python:3.10-alpine 13 | 14 | RUN apk add --update caddy gcc musl-dev libffi-dev 15 | 16 | WORKDIR /app 17 | COPY backend/requirements.txt /tmp/requirements.txt 18 | RUN pip install --no-cache-dir -r /tmp/requirements.txt 19 | 20 | COPY Caddyfile ./Caddyfile 21 | COPY backend ./backend 22 | COPY --from=FrontendBuilder /app/frontend/dist ./dist 23 | 24 | EXPOSE 80 25 | 26 | COPY startup.sh ./startup.sh 27 | RUN chmod +x ./startup.sh; mkdir /data 28 | CMD ["/app/startup.sh"] 29 | -------------------------------------------------------------------------------- /README.en.md: -------------------------------------------------------------------------------- 1 |
23 | {{ code }}
24 |
25 |
35 | {{ content }}
36 |
37 |
25 | {{ props.request }}
26 |
27 |
42 | {{ props.response }}
43 |
44 | elements in the document. 60 | const preTags = doc.getElementsByTagName('pre'); 61 | 62 | // Loop through theelements and add a