Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions cmd/agents_files.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package cmd

import (
"fmt"

"github.com/nextlevelbuilder/goclaw-cli/internal/output"
"github.com/spf13/cobra"
)

var agentsFilesCmd = &cobra.Command{
Use: "files",
Short: "Manage agent context files",
}

var agentsFilesListCmd = &cobra.Command{
Use: "list <agentID>", Short: "List agent files", Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
ws, err := newWS("cli")
if err != nil {
return err
}
if _, err := ws.Connect(); err != nil {
return err
}
defer ws.Close()
data, err := ws.Call("agents.files.list", map[string]any{"agent_id": args[0]})
if err != nil {
return err
}
if cfg.OutputFormat != "table" {
printer.Print(unmarshalList(data))
return nil
}
tbl := output.NewTable("NAME", "SIZE", "UPDATED")
for _, f := range unmarshalList(data) {
tbl.AddRow(str(f, "name"), str(f, "size"), str(f, "updated_at"))
}
printer.Print(tbl)
return nil
},
}

var agentsFilesGetCmd = &cobra.Command{
Use: "get <agentID> <fileName>", Short: "Get agent file content", Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
ws, err := newWS("cli")
if err != nil {
return err
}
if _, err := ws.Connect(); err != nil {
return err
}
defer ws.Close()
data, err := ws.Call("agents.files.get", map[string]any{"agent_id": args[0], "file_name": args[1]})
if err != nil {
return err
}
m := unmarshalMap(data)
if content := str(m, "content"); content != "" {
fmt.Println(content)
} else {
printer.Print(m)
}
return nil
},
}

var agentsFilesSetCmd = &cobra.Command{
Use: "set <agentID> <fileName>", Short: "Set agent file content", Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
ws, err := newWS("cli")
if err != nil {
return err
}
if _, err := ws.Connect(); err != nil {
return err
}
defer ws.Close()
contentVal, _ := cmd.Flags().GetString("content")
content, err := readContent(contentVal)
if err != nil {
return err
}
_, err = ws.Call("agents.files.set", map[string]any{
"agent_id": args[0], "file_name": args[1], "content": content,
})
if err != nil {
return err
}
printer.Success("File updated")
return nil
},
}

func init() {
agentsFilesSetCmd.Flags().String("content", "", "Content (or @filepath)")
_ = agentsFilesSetCmd.MarkFlagRequired("content")

agentsFilesCmd.AddCommand(agentsFilesListCmd, agentsFilesGetCmd, agentsFilesSetCmd)
agentsCmd.AddCommand(agentsFilesCmd)
}
29 changes: 29 additions & 0 deletions cmd/agents_wake.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package cmd

import (
"net/url"

"github.com/spf13/cobra"
)

var agentsWakeCmd = &cobra.Command{
Use: "wake <id>",
Short: "Wake up a sleeping agent",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
c, err := newHTTP()
if err != nil {
return err
}
_, err = c.Post("/v1/agents/"+url.PathEscape(args[0])+"/wake", nil)
if err != nil {
return err
}
printer.Success("Agent woken up")
return nil
},
}

func init() {
agentsCmd.AddCommand(agentsWakeCmd)
}
6 changes: 6 additions & 0 deletions cmd/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ func TestAllCommandsRegistered(t *testing.T) {
"credentials",
"cron",
"delegations",
"devices",
"export",
"heartbeat",
"import",
"knowledge-graph",
"logs",
"mcp",
Expand Down Expand Up @@ -99,7 +102,10 @@ func TestCommandUseFields(t *testing.T) {
{"credentials"},
{"cron"},
{"delegations"},
{"devices"},
{"export"},
{"heartbeat"},
{"import"},
{"knowledge-graph"},
{"logs"},
{"mcp"},
Expand Down
86 changes: 86 additions & 0 deletions cmd/devices.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package cmd

import (
"github.com/nextlevelbuilder/goclaw-cli/internal/output"
"github.com/nextlevelbuilder/goclaw-cli/internal/tui"
"github.com/spf13/cobra"
)

var devicesCmd = &cobra.Command{Use: "devices", Short: "Manage paired devices"}

var devicesListCmd = &cobra.Command{
Use: "list", Short: "List paired devices",
RunE: func(cmd *cobra.Command, args []string) error {
ws, err := newWS("cli")
if err != nil {
return err
}
if _, err := ws.Connect(); err != nil {
return err
}
defer ws.Close()
data, err := ws.Call("device.pair.list", map[string]any{})
if err != nil {
return err
}
if cfg.OutputFormat != "table" {
printer.Print(unmarshalList(data))
return nil
}
tbl := output.NewTable("ID", "NAME", "USER", "STATUS", "PAIRED_AT", "LAST_SEEN")
for _, d := range unmarshalList(data) {
tbl.AddRow(str(d, "id"), str(d, "device_name"), str(d, "user_id"),
str(d, "status"), str(d, "paired_at"), str(d, "last_seen_at"))
}
printer.Print(tbl)
return nil
},
}

var devicesRevokeCmd = &cobra.Command{
Use: "revoke <id>", Short: "Revoke a paired device", Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
if !tui.Confirm("Revoke this device?", cfg.Yes) {
return nil
}
ws, err := newWS("cli")
if err != nil {
return err
}
if _, err := ws.Connect(); err != nil {
return err
}
defer ws.Close()
_, err = ws.Call("device.pair.revoke", map[string]any{"id": args[0]})
if err != nil {
return err
}
printer.Success("Device revoked")
return nil
},
}

var devicesPairingStatusCmd = &cobra.Command{
Use: "pairing-status", Short: "Check browser pairing status",
RunE: func(cmd *cobra.Command, args []string) error {
ws, err := newWS("cli")
if err != nil {
return err
}
if _, err := ws.Connect(); err != nil {
return err
}
defer ws.Close()
data, err := ws.Call("browser.pairing.status", map[string]any{})
if err != nil {
return err
}
printer.Print(unmarshalMap(data))
return nil
},
}

func init() {
devicesCmd.AddCommand(devicesListCmd, devicesRevokeCmd, devicesPairingStatusCmd)
rootCmd.AddCommand(devicesCmd)
}
Loading
Loading