9
Makefile
9
Makefile
@@ -1,5 +1,6 @@
|
|||||||
GOCMD?=go
|
GOCMD?=go
|
||||||
IMAGE_NAME?=webui
|
IMAGE_NAME?=webui
|
||||||
|
MCPBOX_IMAGE_NAME?=mcpbox
|
||||||
ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
|
||||||
prepare-tests:
|
prepare-tests:
|
||||||
@@ -23,10 +24,16 @@ build: webui/react-ui/dist
|
|||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run: webui/react-ui/dist
|
run: webui/react-ui/dist
|
||||||
$(GOCMD) run ./
|
LOCALAGI_MCPBOX_URL="http://localhost:9090" $(GOCMD) run ./
|
||||||
|
|
||||||
build-image:
|
build-image:
|
||||||
docker build -t $(IMAGE_NAME) -f Dockerfile.webui .
|
docker build -t $(IMAGE_NAME) -f Dockerfile.webui .
|
||||||
|
|
||||||
image-push:
|
image-push:
|
||||||
docker push $(IMAGE_NAME)
|
docker push $(IMAGE_NAME)
|
||||||
|
|
||||||
|
build-mcpbox:
|
||||||
|
docker build -t $(MCPBOX_IMAGE_NAME) -f Dockerfile.mcpbox .
|
||||||
|
|
||||||
|
run-mcpbox:
|
||||||
|
docker run -v /var/run/docker.sock:/var/run/docker.sock --privileged -p 9090:8080 -ti mcpbox
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package stdio
|
package stdio
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -306,47 +307,110 @@ func (s *Server) handleWebSocket(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
log.Printf("WebSocket connection established for process: %s", id)
|
log.Printf("WebSocket connection established for process: %s", id)
|
||||||
|
|
||||||
|
// Create a done channel to signal process completion
|
||||||
|
done := make(chan struct{})
|
||||||
|
|
||||||
|
// Create buffers to capture output
|
||||||
|
var stdoutBuf, stderrBuf bytes.Buffer
|
||||||
|
stdoutTee := io.TeeReader(process.Stdout, &stdoutBuf)
|
||||||
|
stderrTee := io.TeeReader(process.Stderr, &stderrBuf)
|
||||||
|
|
||||||
// Handle stdin
|
// Handle stdin
|
||||||
go func() {
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
// Process already done, this is expected
|
||||||
|
default:
|
||||||
|
log.Printf("WebSocket stdin connection closed for process %s", id)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
_, message, err := conn.ReadMessage()
|
_, message, err := conn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("WebSocket stdin read error for process %s: %v", id, err)
|
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseNormalClosure) {
|
||||||
|
log.Printf("WebSocket stdin unexpected error for process %s: %v", id, err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err := process.Stdin.Write(message); err != nil {
|
||||||
|
if err != io.EOF {
|
||||||
|
log.Printf("WebSocket stdin write error for process %s: %v", id, err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
process.Stdin.Write(message)
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Handle stdout
|
// Handle stdout
|
||||||
go func() {
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
// Process already done, this is expected
|
||||||
|
default:
|
||||||
|
log.Printf("WebSocket stdout connection closed for process %s", id)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
buf := make([]byte, 1024)
|
buf := make([]byte, 1024)
|
||||||
for {
|
for {
|
||||||
n, err := process.Stdout.Read(buf)
|
n, err := stdoutTee.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err != io.EOF {
|
||||||
log.Printf("WebSocket stdout read error for process %s: %v", id, err)
|
log.Printf("WebSocket stdout read error for process %s: %v", id, err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := conn.WriteMessage(websocket.TextMessage, buf[:n]); err != nil {
|
||||||
|
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseNormalClosure) {
|
||||||
|
log.Printf("WebSocket stdout write error for process %s: %v", id, err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
conn.WriteMessage(websocket.TextMessage, buf[:n])
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Handle stderr
|
// Handle stderr
|
||||||
go func() {
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
// Process already done, this is expected
|
||||||
|
default:
|
||||||
|
log.Printf("WebSocket stderr connection closed for process %s", id)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
buf := make([]byte, 1024)
|
buf := make([]byte, 1024)
|
||||||
for {
|
for {
|
||||||
n, err := process.Stderr.Read(buf)
|
n, err := stderrTee.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err != io.EOF {
|
||||||
log.Printf("WebSocket stderr read error for process %s: %v", id, err)
|
log.Printf("WebSocket stderr read error for process %s: %v", id, err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := conn.WriteMessage(websocket.TextMessage, buf[:n]); err != nil {
|
||||||
|
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseNormalClosure) {
|
||||||
|
log.Printf("WebSocket stderr write error for process %s: %v", id, err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
conn.WriteMessage(websocket.TextMessage, buf[:n])
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Wait for process to exit
|
// Wait for process to exit
|
||||||
process.Cmd.Wait()
|
err = process.Cmd.Wait()
|
||||||
log.Printf("Process %s exited", id)
|
close(done) // Signal that the process is done
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Process %s exited with error: %v\nstdout: %s\nstderr: %s",
|
||||||
|
id, err, stdoutBuf.String(), stderrBuf.String())
|
||||||
|
} else {
|
||||||
|
log.Printf("Process %s exited successfully", id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add new handlers for group management
|
// Add new handlers for group management
|
||||||
|
|||||||
Reference in New Issue
Block a user