Browse Source

feat(frontend): Display runtime ID in the browser console if available (#4978)

sp.wack 1 year ago
parent
commit
9cd248d475

+ 7 - 0
frontend/src/api/open-hands.ts

@@ -183,6 +183,13 @@ class OpenHands {
   static async getVSCodeUrl(): Promise<GetVSCodeUrlResponse> {
   static async getVSCodeUrl(): Promise<GetVSCodeUrlResponse> {
     return request(`/api/vscode-url`, {}, false, false, 1);
     return request(`/api/vscode-url`, {}, false, false, 1);
   }
   }
+
+  static async getRuntimeId(): Promise<{ runtime_id: string }> {
+    const response = await request("/api/config");
+    const data = await response.json();
+
+    return data;
+  }
 }
 }
 
 
 export default OpenHands;
 export default OpenHands;

+ 23 - 2
frontend/src/components/chat-interface.tsx

@@ -21,14 +21,18 @@ import { ScrollToBottomButton } from "./scroll-to-bottom-button";
 import { Suggestions } from "./suggestions";
 import { Suggestions } from "./suggestions";
 import { SUGGESTIONS } from "#/utils/suggestions";
 import { SUGGESTIONS } from "#/utils/suggestions";
 import BuildIt from "#/icons/build-it.svg?react";
 import BuildIt from "#/icons/build-it.svg?react";
-import { useWsClient } from "#/context/ws-client-provider";
+import {
+  useWsClient,
+  WsClientProviderStatus,
+} from "#/context/ws-client-provider";
+import OpenHands from "#/api/open-hands";
 
 
 const isErrorMessage = (
 const isErrorMessage = (
   message: Message | ErrorMessage,
   message: Message | ErrorMessage,
 ): message is ErrorMessage => "error" in message;
 ): message is ErrorMessage => "error" in message;
 
 
 export function ChatInterface() {
 export function ChatInterface() {
-  const { send, isLoadingMessages } = useWsClient();
+  const { send, status, isLoadingMessages } = useWsClient();
 
 
   const dispatch = useDispatch();
   const dispatch = useDispatch();
   const scrollRef = React.useRef<HTMLDivElement>(null);
   const scrollRef = React.useRef<HTMLDivElement>(null);
@@ -44,6 +48,23 @@ export function ChatInterface() {
   const [feedbackModalIsOpen, setFeedbackModalIsOpen] = React.useState(false);
   const [feedbackModalIsOpen, setFeedbackModalIsOpen] = React.useState(false);
   const [messageToSend, setMessageToSend] = React.useState<string | null>(null);
   const [messageToSend, setMessageToSend] = React.useState<string | null>(null);
 
 
+  React.useEffect(() => {
+    if (status === WsClientProviderStatus.ACTIVE) {
+      try {
+        OpenHands.getRuntimeId().then(({ runtime_id }) => {
+          // eslint-disable-next-line no-console
+          console.log(
+            "Runtime ID: %c%s",
+            "background: #444; color: #ffeb3b; font-weight: bold; padding: 2px 4px; border-radius: 4px;",
+            runtime_id,
+          );
+        });
+      } catch (e) {
+        console.warn("Runtime ID not available in this environment");
+      }
+    }
+  }, [status]);
+
   const handleSendMessage = async (content: string, files: File[]) => {
   const handleSendMessage = async (content: string, files: File[]) => {
     posthog.capture("user_message_sent", {
     posthog.capture("user_message_sent", {
       current_message_count: messages.length,
       current_message_count: messages.length,

+ 24 - 0
openhands/server/listen.py

@@ -11,6 +11,7 @@ import requests
 from pathspec import PathSpec
 from pathspec import PathSpec
 from pathspec.patterns import GitWildMatchPattern
 from pathspec.patterns import GitWildMatchPattern
 
 
+from openhands.runtime.impl.remote.remote_runtime import RemoteRuntime
 from openhands.security.options import SecurityAnalyzers
 from openhands.security.options import SecurityAnalyzers
 from openhands.server.data_models.feedback import FeedbackDataModel, store_feedback
 from openhands.server.data_models.feedback import FeedbackDataModel, store_feedback
 from openhands.server.github import (
 from openhands.server.github import (
@@ -564,6 +565,29 @@ def sanitize_filename(filename):
     return filename
     return filename
 
 
 
 
+@app.get('/api/config')
+async def get_remote_runtime_config(request: Request):
+    """Retrieve the remote runtime configuration.
+
+    Currently, this is the runtime ID.
+    """
+    try:
+        runtime = request.state.conversation.runtime
+        if isinstance(runtime, RemoteRuntime):
+            return JSONResponse(content={'runtime_id': runtime.runtime_id})
+        else:
+            return JSONResponse(
+                status_code=status.HTTP_404_NOT_FOUND,
+                content={'error': 'Runtime ID not available in this environment'},
+            )
+    except Exception as e:
+        logger.error(e)
+        return JSONResponse(
+            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
+            content={'error': 'Something went wrong'},
+        )
+
+
 @app.post('/api/upload-files')
 @app.post('/api/upload-files')
 async def upload_file(request: Request, files: list[UploadFile]):
 async def upload_file(request: Request, files: list[UploadFile]):
     """Upload a list of files to the workspace.
     """Upload a list of files to the workspace.