feat: connect frontend terminal to terminal service

fix: use ReconnectWebSocket to make the connection more stable

fix: typescript error on importing css in vue
This commit is contained in:
Justin Lin committed 2025-05-05 19:55:35 +08:00
1 parent 9c9456693d
commit c7e6d31b9c
12 files changed
+84 -9

No files matched your search

+5 -1
View File
@@ -22,7 +22,11 @@ const tasks = computed(() => {
<div class="h-full w-full max-h-full">
<p id="topic" class="text-text font-black" v-if="sessionStore.quest">
{{ sessionStore.quest.title }}
{{ sessionStore.session?.token }}
<a
:href="`http://localhost/terminal/${sessionStore.session?.containerName}?token=${sessionStore.session?.token}`"
>
Open Terminal
</a>
</p>
<br />
<div>
+4
View File
@@ -50,8 +50,12 @@ const useSession = defineStore('session', {
...session,
graph: new FileGraph(session.graph),
pwd: '/home/commander',
containerName: session.containerName || '',
}
term.reset()
term.connect(
`/terminal/${session.containerName}/ws?token=${session.token}`
)
await socket.connect(this.session)
term.focus()
},
+1
View File
@@ -22,4 +22,5 @@ export interface Session {
tasks: ITask[]
responses: IResponse[]
token: string
containerName: string
}
+4
View File
@@ -0,0 +1,4 @@
declare module '*.css' {
const content: string
export default content
}
+37 -4
View File
@@ -1,10 +1,12 @@
import { Terminal } from 'xterm'
import { FitAddon } from 'xterm-addon-fit'
import ReconnectingWebSocket from 'reconnecting-websocket'
import 'xterm/css/xterm.css'
class SocketTerminal {
private term: Terminal
private fitAddon: FitAddon
private socket: ReconnectingWebSocket | null = null
constructor() {
this.term = new Terminal({
@@ -19,6 +21,40 @@ class SocketTerminal {
})
this.fitAddon = new FitAddon()
this.term.loadAddon(this.fitAddon)
this.term.onData((data) => {
if (this.socket) {
this.socket.send(data)
}
})
}
connect(url: string): void {
console.log('Connecting to terminal', url)
this.socket = new ReconnectingWebSocket(url)
this.socket.onopen = () => {
console.log('Connected to terminal')
this.term.write('\r\n\x1B[1;32mConnected to terminal\x1B[0m\r\n')
}
this.socket.onclose = () => {
console.log('Disconnected from terminal')
this.term.write('\r\n\x1B[1;31mDisconnected from terminal\x1B[0m\r\n')
}
this.socket.onerror = (error) => {
console.error('WebSocket error:', error)
this.term.write(
`\r\n\x1B[1;31mWebSocket error: ${'message' in error ? error.message : ''}\x1B[0m\r\n`
)
}
this.socket.onmessage = (event) => {
console.log('Received message from terminal')
const data =
typeof event.data === 'string'
? event.data
: new TextDecoder().decode(event.data)
this.term.write(data)
}
}
resizeScreen(): void {
@@ -38,16 +74,13 @@ class SocketTerminal {
this.term.write(message)
}
onData(callback: (data: string) => void): void {
this.term.onData(callback)
}
focus(): void {
this.term.focus()
}
reset(): void {
this.term.reset()
this.socket?.close()
}
}