fix(cmd): add --user flag to agent chat for user_id authentication (#714)

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) <noreply@anthropic.com>
This commit is contained in:
Stanley KaoandClaude Opus 4.6 authored and GitHub committed 2026-08-07 01:31:02 +07:00
1 parent 94d2799788
commit cc510d924e
2 files changed
+11 -6

No files matched your search

+5 -3
View File
@@ -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 ---
+6 -3
View File
@@ -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,7 +79,7 @@ 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{}
userId := os.Getenv("GOCLAW_USER_ID")
if userId == "" { userId = "system" }
@@ -87,6 +87,9 @@ func wsConnect(conn *websocket.Conn, token string) error {
if token != "" {
params["token"] = token
}
if userID != "" {
params["user_id"] = userID
}
paramsJSON, _ := json.Marshal(params)
reqFrame := protocol.RequestFrame{