mirror of
https://github.com/sipeed/NanoKVM.git
synced 2026-09-11 00:22:56 -05:00
Add an MCP Streamable HTTP server with token authentication, screenshot capture, keyboard, and mouse tools. Introduce shared control-mode and input-control coordination so MCP, PicoClaw, and local HID paths serialize ownership safely. Integrate PicoClaw gateway/runtime control handoff with PID-managed startup and focused unit coverage.
83 lines
1.8 KiB
Go
83 lines
1.8 KiB
Go
package picoclaw
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
const (
|
|
CodePicoclawLockHeld = "AI_LOCK_HELD"
|
|
CodeScreenshotFailed = "SCREENSHOT_FAILED"
|
|
CodeScreenshotNoSignal = "SCREENSHOT_NO_SIGNAL"
|
|
CodeHIDWriteFailed = "HID_WRITE_FAILED"
|
|
CodeInvalidAction = "INVALID_ACTION"
|
|
CodeRuntimeUnavailable = "RUNTIME_UNAVAILABLE"
|
|
CodeRuntimeStartFailed = "RUNTIME_START_FAILED"
|
|
CodeSessionIDMissing = "SESSION_ID_MISSING"
|
|
CodeSessionIDInvalid = "SESSION_ID_INVALID"
|
|
CodeControlModeConflict = "AI_MODE_CONFLICT"
|
|
CodeControlRequired = "CONTROL_REQUIRED"
|
|
CodeControlOwnedByMCP = "CONTROL_OWNED_BY_MCP"
|
|
CodeControlTransitioning = "CONTROL_TRANSITIONING"
|
|
)
|
|
|
|
type PicoclawError struct {
|
|
StatusCode int
|
|
Code string
|
|
Message string
|
|
SessionID string
|
|
Index *int
|
|
}
|
|
|
|
func (e *PicoclawError) Error() string {
|
|
return e.Code + ": " + e.Message
|
|
}
|
|
|
|
func newPicoclawError(code string, message string) *PicoclawError {
|
|
return &PicoclawError{
|
|
StatusCode: http.StatusOK,
|
|
Code: code,
|
|
Message: message,
|
|
}
|
|
}
|
|
|
|
func writeSuccess(c *gin.Context, data interface{}) {
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 0,
|
|
"msg": "success",
|
|
"data": data,
|
|
})
|
|
}
|
|
|
|
func writePicoclawError(c *gin.Context, err *PicoclawError) {
|
|
writePicoclawErrorWithData(c, err, nil)
|
|
}
|
|
|
|
func writePicoclawErrorWithData(c *gin.Context, err *PicoclawError, data interface{}) {
|
|
if err == nil {
|
|
return
|
|
}
|
|
|
|
payload := gin.H{
|
|
"code": err.Code,
|
|
"message": err.Message,
|
|
}
|
|
if data != nil {
|
|
payload["data"] = data
|
|
}
|
|
if err.SessionID != "" {
|
|
payload["session_id"] = err.SessionID
|
|
}
|
|
if err.Index != nil {
|
|
payload["index"] = *err.Index
|
|
}
|
|
|
|
statusCode := err.StatusCode
|
|
if statusCode == 0 {
|
|
statusCode = http.StatusOK
|
|
}
|
|
|
|
c.JSON(statusCode, payload)
|
|
}
|