mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
Fix: Keypresses in Terminal throws exception (#71)
This commit is contained in:
parent
0380070e98
commit
a722f5c0b1
@ -18,6 +18,7 @@
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {
|
||||
"no-underscore-dangle": "off",
|
||||
"jsx-a11y/no-static-element-interactions": "off",
|
||||
"jsx-a11y/click-events-have-key-events": "off",
|
||||
"react/no-array-index-key": "off"
|
||||
|
||||
9
frontend/package-lock.json
generated
9
frontend/package-lock.json
generated
@ -26,7 +26,6 @@
|
||||
"vite": "^5.1.6",
|
||||
"vite-tsconfig-paths": "^4.3.2",
|
||||
"web-vitals": "^2.1.4",
|
||||
"xterm-addon-attach": "^0.9.0",
|
||||
"xterm-addon-fit": "^0.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -9553,14 +9552,6 @@
|
||||
"integrity": "sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/xterm-addon-attach": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/xterm-addon-attach/-/xterm-addon-attach-0.9.0.tgz",
|
||||
"integrity": "sha512-NykWWOsobVZPPK3P9eFkItrnBK9Lw0f94uey5zhqIVB1bhswdVBfl+uziEzSOhe2h0rT9wD0wOeAYsdSXeavPw==",
|
||||
"peerDependencies": {
|
||||
"xterm": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xterm-addon-fit": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/xterm-addon-fit/-/xterm-addon-fit-0.8.0.tgz",
|
||||
|
||||
@ -22,7 +22,6 @@
|
||||
"vite": "^5.1.6",
|
||||
"vite-tsconfig-paths": "^4.3.2",
|
||||
"web-vitals": "^2.1.4",
|
||||
"xterm-addon-attach": "^0.9.0",
|
||||
"xterm-addon-fit": "^0.8.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@ -1,9 +1,39 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { Terminal as XtermTerminal } from "@xterm/xterm";
|
||||
import { AttachAddon } from "xterm-addon-attach";
|
||||
import { IDisposable, Terminal as XtermTerminal } from "@xterm/xterm";
|
||||
import { FitAddon } from "xterm-addon-fit";
|
||||
import "@xterm/xterm/css/xterm.css";
|
||||
|
||||
class JsonWebsocketAddon {
|
||||
_socket: WebSocket;
|
||||
|
||||
_disposables: IDisposable[];
|
||||
|
||||
constructor(socket: WebSocket) {
|
||||
this._socket = socket;
|
||||
this._disposables = [];
|
||||
}
|
||||
|
||||
activate(terminal: XtermTerminal) {
|
||||
this._disposables.push(
|
||||
terminal.onData((data) => {
|
||||
const payload = JSON.stringify({ action: "terminal", data });
|
||||
this._socket.send(payload);
|
||||
}),
|
||||
);
|
||||
this._socket.addEventListener("message", (event) => {
|
||||
const { message } = JSON.parse(event.data);
|
||||
if (message.action === "terminal") {
|
||||
terminal.write(message.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._disposables.forEach((d) => d.dispose());
|
||||
this._socket.removeEventListener("message", () => {});
|
||||
}
|
||||
}
|
||||
|
||||
function Terminal(): JSX.Element {
|
||||
const terminalRef = useRef<HTMLDivElement>(null);
|
||||
const WS_URL = import.meta.env.VITE_TERMINAL_WS_URL;
|
||||
@ -32,11 +62,12 @@ function Terminal(): JSX.Element {
|
||||
|
||||
if (!WS_URL) {
|
||||
throw new Error(
|
||||
"The environment variable REACT_APP_TERMINAL_WS_URL is not set. Please set it to the WebSocket URL of the terminal server.",
|
||||
"The environment variable VITE_TERMINAL_WS_URL is not set. Please set it to the WebSocket URL of the terminal server.",
|
||||
);
|
||||
}
|
||||
const attachAddon = new AttachAddon(new WebSocket(WS_URL as string));
|
||||
terminal.loadAddon(attachAddon);
|
||||
const socket = new WebSocket(WS_URL as string);
|
||||
const jsonWebsocketAddon = new JsonWebsocketAddon(socket);
|
||||
terminal.loadAddon(jsonWebsocketAddon);
|
||||
|
||||
return () => {
|
||||
terminal.dispose();
|
||||
|
||||
@ -57,6 +57,12 @@ async def websocket_endpoint(websocket: WebSocket):
|
||||
continue
|
||||
|
||||
agent_listener = asyncio.create_task(listen_for_agent_messages())
|
||||
if action == "terminal":
|
||||
msg = {
|
||||
"action": "terminal",
|
||||
"data": data["data"]
|
||||
}
|
||||
await send_message_to_client(get_message_payload(msg))
|
||||
else:
|
||||
if agent_websocket is None:
|
||||
await send_message_to_client(get_error_payload("Agent not connected"))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user