Files
goclaw/cmd/sessions_cmd.go
Viet Tran 6895e369f6 refactor: remove standalone mode, consolidate to managed-only (PostgreSQL) (#70)
- Remove standalone mode code: file-based stores, standalone gateway,
  heartbeat service, SQLite memory, standalone docker-compose
- Rename docker-compose.managed.yml → docker-compose.postgres.yml
- Clean up ~130 Go comments referencing "managed mode" qualifier
- Simplify docker-compose.yml env vars (providers/channels via web UI)
- Update .env.example to essential vars only (token + encryption key)
- Add setup wizard UI (provider → agent → channel bootstrap flow)
- Add logs.tail WebSocket handler for live log streaming
- Add cursor-pointer to interactive UI components
- Clean up config page (remove standalone-only sections)
- Update README and docs for managed-only architecture
2026-03-06 18:51:11 +07:00

158 lines
3.5 KiB
Go

package cmd
import (
"encoding/json"
"fmt"
"os"
"text/tabwriter"
"time"
"github.com/spf13/cobra"
"github.com/nextlevelbuilder/goclaw/internal/store"
"github.com/nextlevelbuilder/goclaw/pkg/protocol"
)
func sessionsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "sessions",
Short: "View and manage chat sessions",
}
cmd.AddCommand(sessionsListCmd())
cmd.AddCommand(sessionsDeleteCmd())
cmd.AddCommand(sessionsResetCmd())
return cmd
}
func sessionsListCmd() *cobra.Command {
var jsonOutput bool
var agentFilter string
cmd := &cobra.Command{
Use: "list",
Short: "List all sessions",
Run: func(cmd *cobra.Command, args []string) {
sessionsListRPC(agentFilter, jsonOutput)
},
}
cmd.Flags().BoolVar(&jsonOutput, "json", false, "output as JSON")
cmd.Flags().StringVar(&agentFilter, "agent", "", "filter by agent ID")
return cmd
}
func sessionsDeleteCmd() *cobra.Command {
return &cobra.Command{
Use: "delete [key]",
Short: "Delete a session",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
sessionsDeleteRPC(args[0])
},
}
}
func sessionsResetCmd() *cobra.Command {
return &cobra.Command{
Use: "reset [key]",
Short: "Clear session history (keep session)",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
sessionsResetRPC(args[0])
},
}
}
// --- RPC implementations ---
func sessionsListRPC(agentFilter string, jsonOutput bool) {
requireGateway()
params, _ := json.Marshal(map[string]string{"agentId": agentFilter})
resp, err := gatewayRPC(protocol.MethodSessionsList, params)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
if !resp.OK {
fmt.Fprintf(os.Stderr, "Failed: %s\n", resp.Error.Message)
os.Exit(1)
}
// Parse response payload → []store.SessionInfo
raw, _ := json.Marshal(resp.Payload)
var result struct {
Sessions []store.SessionInfo `json:"sessions"`
}
if err := json.Unmarshal(raw, &result); err != nil {
fmt.Fprintf(os.Stderr, "Error parsing response: %v\n", err)
os.Exit(1)
}
printSessionInfos(result.Sessions, jsonOutput)
}
func sessionsDeleteRPC(key string) {
requireGateway()
params, _ := json.Marshal(map[string]string{"key": key})
resp, err := gatewayRPC(protocol.MethodSessionsDelete, params)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
if !resp.OK {
fmt.Fprintf(os.Stderr, "Failed: %s\n", resp.Error.Message)
os.Exit(1)
}
fmt.Printf("Deleted session: %s\n", key)
}
func sessionsResetRPC(key string) {
requireGateway()
params, _ := json.Marshal(map[string]string{"key": key})
resp, err := gatewayRPC(protocol.MethodSessionsReset, params)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
if !resp.OK {
fmt.Fprintf(os.Stderr, "Failed: %s\n", resp.Error.Message)
os.Exit(1)
}
fmt.Printf("Reset session: %s\n", key)
}
// --- Shared display ---
func printSessionInfos(infos []store.SessionInfo, jsonOutput bool) {
if jsonOutput {
data, _ := json.MarshalIndent(infos, "", " ")
fmt.Println(string(data))
return
}
if len(infos) == 0 {
fmt.Println("No sessions found.")
return
}
tw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
fmt.Fprintf(tw, "KEY\tMESSAGES\tCREATED\tUPDATED\n")
for _, s := range infos {
fmt.Fprintf(tw, "%s\t%d\t%s\t%s\n",
truncateStr(s.Key, 50),
s.MessageCount,
s.Created.Format(time.DateTime),
s.Updated.Format(time.DateTime),
)
}
tw.Flush()
}
func truncateStr(s string, max int) string {
if len(s) <= max {
return s
}
return s[:max-3] + "..."
}