fix lint error
This commit is contained in:
parent
a63956d818
commit
56caa7a34b
3 changed files with 29 additions and 28 deletions
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
|
|
||||||
"github.com/sipeed/picoclaw/pkg/bus"
|
"github.com/sipeed/picoclaw/pkg/bus"
|
||||||
"github.com/sipeed/picoclaw/pkg/config"
|
"github.com/sipeed/picoclaw/pkg/config"
|
||||||
"github.com/sipeed/picoclaw/pkg/logger"
|
"github.com/sipeed/picoclaw/pkg/logger"
|
||||||
|
|
@ -146,7 +147,7 @@ func (c *Channel) Start(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
c.setRunning(true)
|
c.setRunning(true)
|
||||||
logger.InfoCF("websocket", "WebSocket channel starting", map[string]interface{}{
|
logger.InfoCF("websocket", "WebSocket channel starting", map[string]any{
|
||||||
"address": addr,
|
"address": addr,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -164,7 +165,7 @@ func (c *Channel) Start(ctx context.Context) error {
|
||||||
c.setRunning(false)
|
c.setRunning(false)
|
||||||
return fmt.Errorf("failed to start WebSocket server: %w", err)
|
return fmt.Errorf("failed to start WebSocket server: %w", err)
|
||||||
case <-time.After(100 * time.Millisecond):
|
case <-time.After(100 * time.Millisecond):
|
||||||
logger.InfoCF("websocket", "WebSocket channel started successfully", map[string]interface{}{
|
logger.InfoCF("websocket", "WebSocket channel started successfully", map[string]any{
|
||||||
"address": addr,
|
"address": addr,
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -180,7 +181,7 @@ func (c *Channel) Stop(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close all client connections
|
// Close all client connections
|
||||||
c.clients.Range(func(key, value interface{}) bool {
|
c.clients.Range(func(key, value any) bool {
|
||||||
if conn, ok := value.(*websocket.Conn); ok {
|
if conn, ok := value.(*websocket.Conn); ok {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}
|
}
|
||||||
|
|
@ -193,7 +194,7 @@ func (c *Channel) Stop(ctx context.Context) error {
|
||||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
if err := c.server.Shutdown(shutdownCtx); err != nil {
|
if err := c.server.Shutdown(shutdownCtx); err != nil {
|
||||||
logger.ErrorCF("websocket", "Error shutting down server", map[string]interface{}{
|
logger.ErrorCF("websocket", "Error shutting down server", map[string]any{
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -224,7 +225,7 @@ func (c *Channel) Send(ctx context.Context, msg bus.OutboundMessage) error {
|
||||||
|
|
||||||
// Ensure UTF-8 validity
|
// Ensure UTF-8 validity
|
||||||
if !json.Valid(data) {
|
if !json.Valid(data) {
|
||||||
logger.ErrorCF("websocket", "Invalid JSON data", map[string]interface{}{
|
logger.ErrorCF("websocket", "Invalid JSON data", map[string]any{
|
||||||
"content_preview": msg.Content[:min(len(msg.Content), 100)],
|
"content_preview": msg.Content[:min(len(msg.Content), 100)],
|
||||||
})
|
})
|
||||||
return fmt.Errorf("invalid JSON message")
|
return fmt.Errorf("invalid JSON message")
|
||||||
|
|
@ -238,7 +239,7 @@ func (c *Channel) Send(ctx context.Context, msg bus.OutboundMessage) error {
|
||||||
err := wsConn.WriteMessage(websocket.TextMessage, data)
|
err := wsConn.WriteMessage(websocket.TextMessage, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Connection may be dead, clean it up
|
// Connection may be dead, clean it up
|
||||||
logger.WarnCF("websocket", "Failed to send to client, removing connection", map[string]interface{}{
|
logger.WarnCF("websocket", "Failed to send to client, removing connection", map[string]any{
|
||||||
"client": msg.ChatID,
|
"client": msg.ChatID,
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
|
|
@ -253,11 +254,11 @@ func (c *Channel) Send(ctx context.Context, msg bus.OutboundMessage) error {
|
||||||
|
|
||||||
// Broadcast to all connected clients
|
// Broadcast to all connected clients
|
||||||
var lastErr error
|
var lastErr error
|
||||||
deadClients := make([]interface{}, 0)
|
deadClients := make([]any, 0)
|
||||||
c.clients.Range(func(key, value interface{}) bool {
|
c.clients.Range(func(key, value any) bool {
|
||||||
if conn, ok := value.(*websocket.Conn); ok {
|
if conn, ok := value.(*websocket.Conn); ok {
|
||||||
if err := conn.WriteMessage(websocket.TextMessage, data); err != nil {
|
if err := conn.WriteMessage(websocket.TextMessage, data); err != nil {
|
||||||
logger.WarnCF("websocket", "Failed to send to client", map[string]interface{}{
|
logger.WarnCF("websocket", "Failed to send to client", map[string]any{
|
||||||
"client": key,
|
"client": key,
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
|
|
@ -271,7 +272,7 @@ func (c *Channel) Send(ctx context.Context, msg bus.OutboundMessage) error {
|
||||||
// Clean up dead connections
|
// Clean up dead connections
|
||||||
for _, key := range deadClients {
|
for _, key := range deadClients {
|
||||||
c.clients.Delete(key)
|
c.clients.Delete(key)
|
||||||
logger.InfoCF("websocket", "Removed dead client connection", map[string]interface{}{
|
logger.InfoCF("websocket", "Removed dead client connection", map[string]any{
|
||||||
"client": key,
|
"client": key,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -291,7 +292,7 @@ func min(a, b int) int {
|
||||||
func (c *Channel) handleWebSocket(w http.ResponseWriter, r *http.Request) {
|
func (c *Channel) handleWebSocket(w http.ResponseWriter, r *http.Request) {
|
||||||
conn, err := c.upgrader.Upgrade(w, r, nil)
|
conn, err := c.upgrader.Upgrade(w, r, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.ErrorCF("websocket", "Failed to upgrade connection", map[string]interface{}{
|
logger.ErrorCF("websocket", "Failed to upgrade connection", map[string]any{
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
|
@ -301,7 +302,7 @@ func (c *Channel) handleWebSocket(w http.ResponseWriter, r *http.Request) {
|
||||||
clientID := r.RemoteAddr
|
clientID := r.RemoteAddr
|
||||||
c.clients.Store(clientID, conn)
|
c.clients.Store(clientID, conn)
|
||||||
|
|
||||||
logger.InfoCF("websocket", "New client connected", map[string]interface{}{
|
logger.InfoCF("websocket", "New client connected", map[string]any{
|
||||||
"client_id": clientID,
|
"client_id": clientID,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -314,7 +315,7 @@ func (c *Channel) handleClient(clientID string, conn *websocket.Conn) {
|
||||||
defer func() {
|
defer func() {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
c.clients.Delete(clientID)
|
c.clients.Delete(clientID)
|
||||||
logger.InfoCF("websocket", "Client disconnected", map[string]interface{}{
|
logger.InfoCF("websocket", "Client disconnected", map[string]any{
|
||||||
"client_id": clientID,
|
"client_id": clientID,
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
|
|
@ -340,7 +341,7 @@ func (c *Channel) handleClient(clientID string, conn *websocket.Conn) {
|
||||||
_, message, err := conn.ReadMessage()
|
_, message, err := conn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
|
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
|
||||||
logger.ErrorCF("websocket", "WebSocket error", map[string]interface{}{
|
logger.ErrorCF("websocket", "WebSocket error", map[string]any{
|
||||||
"client_id": clientID,
|
"client_id": clientID,
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
|
|
@ -358,7 +359,7 @@ func (c *Channel) handleClient(clientID string, conn *websocket.Conn) {
|
||||||
case <-pingTicker.C:
|
case <-pingTicker.C:
|
||||||
// Send ping to check connection health
|
// Send ping to check connection health
|
||||||
if err := conn.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(10*time.Second)); err != nil {
|
if err := conn.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(10*time.Second)); err != nil {
|
||||||
logger.WarnCF("websocket", "Failed to send ping", map[string]interface{}{
|
logger.WarnCF("websocket", "Failed to send ping", map[string]any{
|
||||||
"client_id": clientID,
|
"client_id": clientID,
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
|
|
@ -371,7 +372,7 @@ func (c *Channel) handleClient(clientID string, conn *websocket.Conn) {
|
||||||
|
|
||||||
var wsMsg WebSocketMessage
|
var wsMsg WebSocketMessage
|
||||||
if err := json.Unmarshal(message, &wsMsg); err != nil {
|
if err := json.Unmarshal(message, &wsMsg); err != nil {
|
||||||
logger.WarnCF("websocket", "Failed to parse message", map[string]interface{}{
|
logger.WarnCF("websocket", "Failed to parse message", map[string]any{
|
||||||
"client_id": clientID,
|
"client_id": clientID,
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
|
|
@ -382,13 +383,13 @@ func (c *Channel) handleClient(clientID string, conn *websocket.Conn) {
|
||||||
if wsMsg.Type == "chat" {
|
if wsMsg.Type == "chat" {
|
||||||
// Check allowlist
|
// Check allowlist
|
||||||
if !c.IsAllowed(clientID) {
|
if !c.IsAllowed(clientID) {
|
||||||
logger.WarnCF("websocket", "Unauthorized client", map[string]interface{}{
|
logger.WarnCF("websocket", "Unauthorized client", map[string]any{
|
||||||
"client_id": clientID,
|
"client_id": clientID,
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.DebugCF("websocket", "Received message", map[string]interface{}{
|
logger.DebugCF("websocket", "Received message", map[string]any{
|
||||||
"client_id": clientID,
|
"client_id": clientID,
|
||||||
"content": wsMsg.Content,
|
"content": wsMsg.Content,
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -298,9 +298,9 @@ type WeComAppConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebSocketConfig struct {
|
type WebSocketConfig struct {
|
||||||
Enabled bool `json:"enabled" env:"PICOCLAW_CHANNELS_WEBSOCKET_ENABLED"`
|
Enabled bool `json:"enabled" env:"PICOCLAW_CHANNELS_WEBSOCKET_ENABLED"`
|
||||||
Host string `json:"host" env:"PICOCLAW_CHANNELS_WEBSOCKET_HOST"`
|
Host string `json:"host" env:"PICOCLAW_CHANNELS_WEBSOCKET_HOST"`
|
||||||
Port int `json:"port" env:"PICOCLAW_CHANNELS_WEBSOCKET_PORT"`
|
Port int `json:"port" env:"PICOCLAW_CHANNELS_WEBSOCKET_PORT"`
|
||||||
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_WEBSOCKET_ALLOW_FROM"`
|
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_WEBSOCKET_ALLOW_FROM"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -191,15 +191,15 @@ func TestShellTool_WorkingDir_OutsideWorkspace(t *testing.T) {
|
||||||
root := t.TempDir()
|
root := t.TempDir()
|
||||||
workspace := filepath.Join(root, "workspace")
|
workspace := filepath.Join(root, "workspace")
|
||||||
outsideDir := filepath.Join(root, "outside")
|
outsideDir := filepath.Join(root, "outside")
|
||||||
if err := os.MkdirAll(workspace, 0755); err != nil {
|
if err := os.MkdirAll(workspace, 0o755); err != nil {
|
||||||
t.Fatalf("failed to create workspace: %v", err)
|
t.Fatalf("failed to create workspace: %v", err)
|
||||||
}
|
}
|
||||||
if err := os.MkdirAll(outsideDir, 0755); err != nil {
|
if err := os.MkdirAll(outsideDir, 0o755); err != nil {
|
||||||
t.Fatalf("failed to create outside dir: %v", err)
|
t.Fatalf("failed to create outside dir: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tool := NewExecTool(workspace, true)
|
tool := NewExecTool(workspace, true)
|
||||||
result := tool.Execute(context.Background(), map[string]interface{}{
|
result := tool.Execute(context.Background(), map[string]any{
|
||||||
"command": "pwd",
|
"command": "pwd",
|
||||||
"working_dir": outsideDir,
|
"working_dir": outsideDir,
|
||||||
})
|
})
|
||||||
|
|
@ -218,13 +218,13 @@ func TestShellTool_WorkingDir_SymlinkEscape(t *testing.T) {
|
||||||
root := t.TempDir()
|
root := t.TempDir()
|
||||||
workspace := filepath.Join(root, "workspace")
|
workspace := filepath.Join(root, "workspace")
|
||||||
secretDir := filepath.Join(root, "secret")
|
secretDir := filepath.Join(root, "secret")
|
||||||
if err := os.MkdirAll(workspace, 0755); err != nil {
|
if err := os.MkdirAll(workspace, 0o755); err != nil {
|
||||||
t.Fatalf("failed to create workspace: %v", err)
|
t.Fatalf("failed to create workspace: %v", err)
|
||||||
}
|
}
|
||||||
if err := os.MkdirAll(secretDir, 0755); err != nil {
|
if err := os.MkdirAll(secretDir, 0o755); err != nil {
|
||||||
t.Fatalf("failed to create secret dir: %v", err)
|
t.Fatalf("failed to create secret dir: %v", err)
|
||||||
}
|
}
|
||||||
os.WriteFile(filepath.Join(secretDir, "secret.txt"), []byte("top secret"), 0644)
|
os.WriteFile(filepath.Join(secretDir, "secret.txt"), []byte("top secret"), 0o644)
|
||||||
|
|
||||||
// symlink lives inside the workspace but resolves to secretDir outside it
|
// symlink lives inside the workspace but resolves to secretDir outside it
|
||||||
link := filepath.Join(workspace, "escape")
|
link := filepath.Join(workspace, "escape")
|
||||||
|
|
@ -233,7 +233,7 @@ func TestShellTool_WorkingDir_SymlinkEscape(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tool := NewExecTool(workspace, true)
|
tool := NewExecTool(workspace, true)
|
||||||
result := tool.Execute(context.Background(), map[string]interface{}{
|
result := tool.Execute(context.Background(), map[string]any{
|
||||||
"command": "cat secret.txt",
|
"command": "cat secret.txt",
|
||||||
"working_dir": link,
|
"working_dir": link,
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue