diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..089752554 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +public/serviceWorker.js \ No newline at end of file diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 000000000..5b2520eb9 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,33 @@ +name: Publish Docker image + +on: + release: + types: [published] + +jobs: + push_to_registry: + name: Push Docker image to Docker Hub + runs-on: ubuntu-latest + steps: + - name: Check out the repo + uses: actions/checkout@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + with: + images: yidadaa/chatgpt-next-web + + - name: Build and push Docker image + uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..314d6c365 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,44 @@ +FROM node:18-alpine AS base + +FROM base AS deps + +RUN apk add --no-cache libc6-compat + +WORKDIR /app + +COPY package.json yarn.lock* package-lock.json* ./ + +RUN \ + if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ + elif [ -f package-lock.json ]; then npm ci; \ + else echo "Lockfile not found." && exit 1; \ + fi + +FROM base AS builder + +RUN apk update && apk add --no-cache git + +ENV OPENAI_API_KEY="" +ENV CODE="" +ARG DOCKER=true + +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +RUN yarn build + +FROM base AS runner +WORKDIR /app + +ENV OPENAI_API_KEY="" +ENV CODE="" + +COPY --from=builder /app/public ./public +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder /app/.next/static ./.next/static +COPY --from=builder /app/.next/server ./.next/server + +EXPOSE 3000 + +CMD ["node","server.js"] diff --git a/README.md b/README.md index f20debd0b..a0d4e68a0 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ One-Click to deploy your own ChatGPT web UI. -[演示 Demo](https://chat-gpt-next-web.vercel.app/) / [反馈 Issues](https://github.com/Yidadaa/ChatGPT-Next-Web/issues) / [加入 Discord](https://discord.gg/zrhvHCr79N) / [微信群](https://user-images.githubusercontent.com/16968934/227772522-b3ba3713-9206-4c8d-a81f-22300b7c313a.jpg) / [打赏开发者](https://user-images.githubusercontent.com/16968934/227772541-5bcd52d8-61b7-488c-a203-0330d8006e2b.jpg) +[演示 Demo](https://chat-gpt-next-web.vercel.app/) / [反馈 Issues](https://github.com/Yidadaa/ChatGPT-Next-Web/issues) / [加入 Discord](https://discord.gg/zrhvHCr79N) / [QQ 群](https://user-images.githubusercontent.com/16968934/228190818-7dd00845-e9b9-4363-97e5-44c507ac76da.jpeg) / [打赏开发者](https://user-images.githubusercontent.com/16968934/227772541-5bcd52d8-61b7-488c-a203-0330d8006e2b.jpg) [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FYidadaa%2FChatGPT-Next-Web&env=OPENAI_API_KEY&project-name=chatgpt-next-web&repository-name=ChatGPT-Next-Web) @@ -116,31 +116,17 @@ OPENAI_API_KEY= 2. 执行 `yarn install && yarn dev` 即可。 ### 本地部署 Local Deployment - -请直接询问 ChatGPT,使用下列 Prompt: - -``` -如何使用 pm2 和 yarn 部署 nextjs 项目到 ubuntu 服务器上,项目编译命令为 yarn build,启动命令为 yarn start,启动时需要设置环境变量为 OPENAI_API_KEY,端口为 3000,使用 ngnix 做反向代理 +```shell +bash <(curl -s https://raw.githubusercontent.com/Yidadaa/ChatGPT-Next-Web/main/scripts/setup.sh) ``` -Please ask ChatGPT with prompt: -``` -how to deploy nextjs project with pm2 and yarn on my ubuntu server, the build command is `yarn build`, the start command is `yarn start`, the project must start with env var named `OPENAI_API_KEY`, the port is 3000, use ngnix -``` +### 容器部署 Docker Deployment -### Docker Deployment +```shell +docker pull yidadaa/chatgpt-next-web -请直接询问 ChatGPT,使用下列 Prompt: - -``` -如何使用 docker 部署 nextjs 项目到 ubuntu 服务器上,项目编译命令为 yarn build,启动命令为 yarn start,启动时需要设置环境变量为 OPENAI_API_KEY,端口为 3000,使用 ngnix 做反向代理 -``` - -Please ask ChatGPT with prompt: - -``` -how to deploy nextjs project with docker on my ubuntu server, the build command is `yarn build`, the start command is `yarn start`, the project must start with env var named `OPENAI_API_KEY`, the port is 3000, use ngnix +docker run -d -p 3000:3000 -e OPENAI_API_KEY="" -e CODE="" yidadaa/chatgpt-next-web ``` ## 截图 Screenshots @@ -165,6 +151,14 @@ If you would like to contribute your API key, you can email it to the author and [@mushan0x0](https://github.com/mushan0x0) [@ClarenceDan](https://github.com/ClarenceDan) +[@zhangjia](https://github.com/zhangjia) + +### 贡献者 Contributor + +[@AprilNEA](https://github.com/AprilNEA) +[@iSource](https://github.com/iSource) +[@iFwu](https://github.com/iFwu) +[@xiaotianxt](https://github.com/xiaotianxt) ## LICENSE diff --git a/app/api/chat-stream/route.ts b/app/api/chat-stream/route.ts index 8803a4252..ad40c6be1 100644 --- a/app/api/chat-stream/route.ts +++ b/app/api/chat-stream/route.ts @@ -1,4 +1,3 @@ -import type { ChatRequest } from "../chat/typing"; import { createParser } from "eventsource-parser"; import { NextRequest } from "next/server"; diff --git a/app/components/home.tsx b/app/components/home.tsx index 1265149a1..850c51774 100644 --- a/app/components/home.tsx +++ b/app/components/home.tsx @@ -131,10 +131,12 @@ function useSubmitHandler() { (config.submitKey === SubmitKey.AltEnter && e.altKey) || (config.submitKey === SubmitKey.CtrlEnter && e.ctrlKey) || (config.submitKey === SubmitKey.ShiftEnter && e.shiftKey) || + (config.submitKey === SubmitKey.MetaEnter && e.metaKey) || (config.submitKey === SubmitKey.Enter && !e.altKey && !e.ctrlKey && - !e.shiftKey) + !e.shiftKey && + !e.metaKey) ); }; @@ -163,6 +165,7 @@ export function Chat(props: { showSideBar?: () => void }) { setIsLoading(true); onUserInput(userInput).then(() => setIsLoading(false)); setUserInput(""); + inputRef.current?.focus(); }; // stop response @@ -203,6 +206,7 @@ export function Chat(props: { showSideBar?: () => void }) { // for auto-scroll const latestMessageRef = useRef(null); + const inputRef = useRef(null); // wont scroll while hovering messages const [autoScroll, setAutoScroll] = useState(false); @@ -371,6 +375,7 @@ export function Chat(props: { showSideBar?: () => void }) {