From 8f78f19fcdb82a09462315ed0784d1584e50ab7b Mon Sep 17 00:00:00 2001 From: Stanley Kao Date: Mon, 6 Apr 2026 01:07:01 +0000 Subject: [PATCH] fix(cmd): add --user flag to agent chat for user_id authentication The CLI agent chat command connects via WebSocket but never sends user_id in the connect params. The gateway requires user_id for chat.send, making the CLI unusable for any agent interaction. All other clients (browser, Telegram, LINE, etc.) send user_id during connect. The CLI was the only channel missing it. Adds --user / -u flag that passes user_id in the connect frame. Co-Authored-By: Claude Opus 4.6 (1M context) --- cmd/agent_chat.go | 8 +++++--- cmd/agent_chat_client.go | 9 ++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/cmd/agent_chat.go b/cmd/agent_chat.go index d9b73f87b..ff995a2a4 100644 --- a/cmd/agent_chat.go +++ b/cmd/agent_chat.go @@ -15,6 +15,7 @@ import ( func agentChatCmd() *cobra.Command { var ( agentName string + userID string message string sessionKey string ) @@ -30,18 +31,19 @@ Examples: goclaw agent chat -m "What time is it?" # One-shot message goclaw agent chat -s my-session # Continue a session`, Run: func(cmd *cobra.Command, args []string) { - runAgentChat(agentName, message, sessionKey) + runAgentChat(agentName, message, sessionKey, userID) }, } cmd.Flags().StringVarP(&agentName, "name", "n", "default", "agent name") cmd.Flags().StringVarP(&message, "message", "m", "", "one-shot message (omit for interactive mode)") cmd.Flags().StringVarP(&sessionKey, "session", "s", "", "session key (default: auto-generated)") + cmd.Flags().StringVarP(&userID, "user", "u", "", "user ID for authentication") return cmd } -func runAgentChat(agentName, message, sessionKey string) { +func runAgentChat(agentName, message, sessionKey, userID string) { cfgPath := resolveConfigPath() cfg, err := config.Load(cfgPath) if err != nil { @@ -68,7 +70,7 @@ func runAgentChat(agentName, message, sessionKey string) { } fmt.Fprintf(os.Stderr, "Connected to gateway at %s\n", addr) - runClientMode(cfg, addr, agentName, message, sessionKey) + runClientMode(cfg, addr, agentName, message, sessionKey, userID) } // --- Gateway detection --- diff --git a/cmd/agent_chat_client.go b/cmd/agent_chat_client.go index a5f8e51bd..65ab77503 100644 --- a/cmd/agent_chat_client.go +++ b/cmd/agent_chat_client.go @@ -15,7 +15,7 @@ import ( "github.com/nextlevelbuilder/goclaw/pkg/protocol" ) -func runClientMode(cfg *config.Config, addr, agentName, message, sessionKey string) { +func runClientMode(cfg *config.Config, addr, agentName, message, sessionKey, userID string) { wsURL := fmt.Sprintf("ws://%s/ws", addr) conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil) @@ -26,7 +26,7 @@ func runClientMode(cfg *config.Config, addr, agentName, message, sessionKey stri defer conn.Close() // Authenticate - if err := wsConnect(conn, cfg.Gateway.Token); err != nil { + if err := wsConnect(conn, cfg.Gateway.Token, userID); err != nil { fmt.Fprintf(os.Stderr, "Gateway auth failed: %v\n", err) os.Exit(1) } @@ -79,11 +79,14 @@ func runClientMode(cfg *config.Config, addr, agentName, message, sessionKey stri } // wsConnect sends the connect RPC and waits for auth response. -func wsConnect(conn *websocket.Conn, token string) error { +func wsConnect(conn *websocket.Conn, token, userID string) error { params := map[string]string{} if token != "" { params["token"] = token } + if userID != "" { + params["user_id"] = userID + } paramsJSON, _ := json.Marshal(params) reqFrame := protocol.RequestFrame{