Selaa lähdekoodia

feat: support tls. #1234 (#1248)

* feat: support tls.

* update the frontend README.

* Update frontend/README.md

Co-authored-by: Boxuan Li <liboxuan@connect.hku.hk>

---------

Co-authored-by: Boxuan Li <liboxuan@connect.hku.hk>
Leo 1 vuosi sitten
vanhempi
sitoutus
0e572c3e41
5 muutettua tiedostoa jossa 69 lisäystä ja 48 poistoa
  1. 1 1
      Makefile
  2. 4 2
      frontend/.env
  3. 14 10
      frontend/README.md
  4. 48 31
      frontend/vite.config.ts
  5. 2 4
      opendevin/server/listen.py

+ 1 - 1
Makefile

@@ -122,7 +122,7 @@ start-backend:
 # Start frontend
 start-frontend:
 	@echo "$(YELLOW)Starting frontend...$(RESET)"
-	@cd frontend && BACKEND_HOST=$(BACKEND_HOST) FRONTEND_PORT=$(FRONTEND_PORT) npm run start
+	@cd frontend && VITE_BACKEND_HOST=$(BACKEND_HOST) VITE_FRONTEND_PORT=$(FRONTEND_PORT) npm run start
 
 # Run the app
 run:

+ 4 - 2
frontend/.env

@@ -1,2 +1,4 @@
-VITE_URL="http://localhost:3000"
-VITE_WS_URL="ws://localhost:3000/ws"
+VITE_BACKEND_HOST="127.0.0.1:3000"
+VITE_USE_TLS="false"
+VITE_INSECURE_SKIP_VERIFY="false"
+VITE_FRONTEND_PORT="3001"

+ 14 - 10
frontend/README.md

@@ -4,10 +4,10 @@
 
 In the project directory, you can run:
 
-### `npm start`
+### `npm run start -- --port 3001`
 
 Runs the app in the development mode.\
-Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
+Open [http://localhost:3001](http://localhost:3001) to view it in the browser.
 
 The page will reload if you make edits.\
 You will also see any lint errors in the console.
@@ -20,16 +20,20 @@ It correctly bundles React in production mode and optimizes the build for the be
 The build is minified and the filenames include the hashes.\
 Your app is ready to be deployed!
 
+## Environment Variables
+You can set the environment variables in `frontend/.env` to configure the frontend. The following variables are available:
+```javascript
+VITE_BACKEND_HOST="127.0.0.1:3000" // The host of the backend
+VITE_USE_TLS="false"               // Whether to use TLS for the backend(includes HTTPS and WSS) 
+VITE_INSECURE_SKIP_VERIFY="false"  // Whether to skip verifying the backend's certificate. Only takes effect if `VITE_USE_TLS` is true. Don't use this in production!
+VITE_FRONTEND_PORT="3001"          // The port of the frontend
+```
+You can also set the environment variables from outside the project, like `exporter VITE_BACKEND_HOST="127.0.0.1:3000"`.
+
+The outside environment variables will override the ones in the `.env` file.
+
 ## Learn More
 
 You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
 
 To learn React, check out the [React documentation](https://reactjs.org/).
-
-## Terminal
-
-The OpenDevin terminal is powered by [Xterm.js](https://github.com/xtermjs/xterm.js).
-
-The terminal listens for events over a WebSocket connection. The WebSocket URL is specified by the environment variable `VITE_WS_URL` (prepending `VITE_` to environment variable names is necessary to expose them).
-
-A simple websocket server can be found in the `/server` directory.

+ 48 - 31
frontend/vite.config.ts

@@ -1,40 +1,57 @@
 /// <reference types="vitest" />
-import { defineConfig } from "vite";
+import { defineConfig, loadEnv } from "vite";
 import react from "@vitejs/plugin-react";
 import viteTsconfigPaths from "vite-tsconfig-paths";
 
-const BACKEND_HOST = process.env.BACKEND_HOST || "127.0.0.1:3000";
+export default defineConfig(({ mode }) => {
+  const {
+    VITE_BACKEND_HOST = "127.0.0.1:3000",
+    VITE_USE_TLS = "false",
+    VITE_FRONTEND_PORT = "3001",
+    VITE_INSECURE_SKIP_VERIFY = "false",
+  } = loadEnv(mode, process.cwd());
 
-// check BACKEND_HOST is something like "example.com"
-if (!BACKEND_HOST.match(/^([\w\d-]+(\.[\w\d-]+)+(:\d+)?)/)) {
-  throw new Error(
-    `Invalid BACKEND_HOST ${BACKEND_HOST}, example BACKEND_HOST 127.0.0.1:3000`,
-  );
-}
+  const USE_TLS = VITE_USE_TLS === "true";
+  const INSECURE_SKIP_VERIFY = VITE_INSECURE_SKIP_VERIFY === "true";
+  const PROTOCOL = USE_TLS ? "https" : "http";
+  const WS_PROTOCOL = USE_TLS ? "wss" : "ws";
 
-export default defineConfig({
-  // depending on your application, base can also be "/"
-  base: "",
-  plugins: [react(), viteTsconfigPaths()],
-  clearScreen: false,
-  server: {
-    port: process.env.FRONTEND_PORT
-      ? Number.parseInt(process.env.FRONTEND_PORT, 10)
-      : 3001,
-    proxy: {
-      "/api": {
-        target: `http://${BACKEND_HOST}/`,
-        changeOrigin: true,
-      },
-      "/ws": {
-        target: `ws://${BACKEND_HOST}/`,
-        ws: true,
+  const API_URL = `${PROTOCOL}://${VITE_BACKEND_HOST}/`;
+  const WS_URL = `${WS_PROTOCOL}://${VITE_BACKEND_HOST}/`;
+  const FE_PORT = Number.parseInt(VITE_FRONTEND_PORT, 10);
+
+  // check BACKEND_HOST is something like "example.com"
+  if (!VITE_BACKEND_HOST.match(/^([\w\d-]+(\.[\w\d-]+)+(:\d+)?)/)) {
+    throw new Error(
+      `Invalid BACKEND_HOST ${VITE_BACKEND_HOST}, example BACKEND_HOST 127.0.0.1:3000`,
+    );
+  }
+
+  return {
+    // depending on your application, base can also be "/"
+    base: "",
+    plugins: [react(), viteTsconfigPaths()],
+    clearScreen: false,
+    server: {
+      port: FE_PORT,
+      proxy: {
+        "/api": {
+          target: API_URL,
+          changeOrigin: true,
+          secure: !INSECURE_SKIP_VERIFY,
+        },
+        "/ws": {
+          target: WS_URL,
+          ws: true,
+          changeOrigin: true,
+          secure: !INSECURE_SKIP_VERIFY,
+        },
       },
     },
-  },
-  test: {
-    environment: "jsdom",
-    globals: true,
-    setupFiles: ["vitest.setup.ts"],
-  },
+    test: {
+      environment: "jsdom",
+      globals: true,
+      setupFiles: ["vitest.setup.ts"],
+    },
+  };
 });

+ 2 - 4
opendevin/server/listen.py

@@ -38,17 +38,15 @@ async def websocket_endpoint(websocket: WebSocket):
         logger.error('Failed to decode token')
         return
     session_manager.add_session(sid, websocket)
-    # TODO: actually the agent_manager is created for each websocket connection, even if the session id is the same,
-    # we need to manage the agent in memory for reconnecting the same session id to the same agent
     agent_manager.register_agent(sid)
     await session_manager.loop_recv(sid, agent_manager.dispatch)
 
 
 @app.get('/api/litellm-models')
 async def get_litellm_models():
-    '''
+    """
     Get all models supported by LiteLLM.
-    '''
+    """
     return list(set(litellm.model_list + list(litellm.model_cost.keys())))