Skip to content

Commit c742f5d

Browse files
authored
Merge pull request #3 from nextlevelbuilder/feat/complete-cli-commands
feat(cli): complete command coverage for all GoClaw backend APIs
2 parents b0e192c + 0b8417d commit c742f5d

File tree

10 files changed

+856
-0
lines changed

10 files changed

+856
-0
lines changed

cmd/agents_files.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/nextlevelbuilder/goclaw-cli/internal/output"
7+
"github.com/spf13/cobra"
8+
)
9+
10+
var agentsFilesCmd = &cobra.Command{
11+
Use: "files",
12+
Short: "Manage agent context files",
13+
}
14+
15+
var agentsFilesListCmd = &cobra.Command{
16+
Use: "list <agentID>", Short: "List agent files", Args: cobra.ExactArgs(1),
17+
RunE: func(cmd *cobra.Command, args []string) error {
18+
ws, err := newWS("cli")
19+
if err != nil {
20+
return err
21+
}
22+
if _, err := ws.Connect(); err != nil {
23+
return err
24+
}
25+
defer ws.Close()
26+
data, err := ws.Call("agents.files.list", map[string]any{"agent_id": args[0]})
27+
if err != nil {
28+
return err
29+
}
30+
if cfg.OutputFormat != "table" {
31+
printer.Print(unmarshalList(data))
32+
return nil
33+
}
34+
tbl := output.NewTable("NAME", "SIZE", "UPDATED")
35+
for _, f := range unmarshalList(data) {
36+
tbl.AddRow(str(f, "name"), str(f, "size"), str(f, "updated_at"))
37+
}
38+
printer.Print(tbl)
39+
return nil
40+
},
41+
}
42+
43+
var agentsFilesGetCmd = &cobra.Command{
44+
Use: "get <agentID> <fileName>", Short: "Get agent file content", Args: cobra.ExactArgs(2),
45+
RunE: func(cmd *cobra.Command, args []string) error {
46+
ws, err := newWS("cli")
47+
if err != nil {
48+
return err
49+
}
50+
if _, err := ws.Connect(); err != nil {
51+
return err
52+
}
53+
defer ws.Close()
54+
data, err := ws.Call("agents.files.get", map[string]any{"agent_id": args[0], "file_name": args[1]})
55+
if err != nil {
56+
return err
57+
}
58+
m := unmarshalMap(data)
59+
if content := str(m, "content"); content != "" {
60+
fmt.Println(content)
61+
} else {
62+
printer.Print(m)
63+
}
64+
return nil
65+
},
66+
}
67+
68+
var agentsFilesSetCmd = &cobra.Command{
69+
Use: "set <agentID> <fileName>", Short: "Set agent file content", Args: cobra.ExactArgs(2),
70+
RunE: func(cmd *cobra.Command, args []string) error {
71+
ws, err := newWS("cli")
72+
if err != nil {
73+
return err
74+
}
75+
if _, err := ws.Connect(); err != nil {
76+
return err
77+
}
78+
defer ws.Close()
79+
contentVal, _ := cmd.Flags().GetString("content")
80+
content, err := readContent(contentVal)
81+
if err != nil {
82+
return err
83+
}
84+
_, err = ws.Call("agents.files.set", map[string]any{
85+
"agent_id": args[0], "file_name": args[1], "content": content,
86+
})
87+
if err != nil {
88+
return err
89+
}
90+
printer.Success("File updated")
91+
return nil
92+
},
93+
}
94+
95+
func init() {
96+
agentsFilesSetCmd.Flags().String("content", "", "Content (or @filepath)")
97+
_ = agentsFilesSetCmd.MarkFlagRequired("content")
98+
99+
agentsFilesCmd.AddCommand(agentsFilesListCmd, agentsFilesGetCmd, agentsFilesSetCmd)
100+
agentsCmd.AddCommand(agentsFilesCmd)
101+
}

cmd/agents_wake.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package cmd
2+
3+
import (
4+
"net/url"
5+
6+
"github.com/spf13/cobra"
7+
)
8+
9+
var agentsWakeCmd = &cobra.Command{
10+
Use: "wake <id>",
11+
Short: "Wake up a sleeping agent",
12+
Args: cobra.ExactArgs(1),
13+
RunE: func(cmd *cobra.Command, args []string) error {
14+
c, err := newHTTP()
15+
if err != nil {
16+
return err
17+
}
18+
_, err = c.Post("/v1/agents/"+url.PathEscape(args[0])+"/wake", nil)
19+
if err != nil {
20+
return err
21+
}
22+
printer.Success("Agent woken up")
23+
return nil
24+
},
25+
}
26+
27+
func init() {
28+
agentsCmd.AddCommand(agentsWakeCmd)
29+
}

cmd/cmd_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ func TestAllCommandsRegistered(t *testing.T) {
2828
"credentials",
2929
"cron",
3030
"delegations",
31+
"devices",
32+
"export",
3133
"heartbeat",
34+
"import",
3235
"knowledge-graph",
3336
"logs",
3437
"mcp",
@@ -99,7 +102,10 @@ func TestCommandUseFields(t *testing.T) {
99102
{"credentials"},
100103
{"cron"},
101104
{"delegations"},
105+
{"devices"},
106+
{"export"},
102107
{"heartbeat"},
108+
{"import"},
103109
{"knowledge-graph"},
104110
{"logs"},
105111
{"mcp"},

cmd/devices.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package cmd
2+
3+
import (
4+
"github.com/nextlevelbuilder/goclaw-cli/internal/output"
5+
"github.com/nextlevelbuilder/goclaw-cli/internal/tui"
6+
"github.com/spf13/cobra"
7+
)
8+
9+
var devicesCmd = &cobra.Command{Use: "devices", Short: "Manage paired devices"}
10+
11+
var devicesListCmd = &cobra.Command{
12+
Use: "list", Short: "List paired devices",
13+
RunE: func(cmd *cobra.Command, args []string) error {
14+
ws, err := newWS("cli")
15+
if err != nil {
16+
return err
17+
}
18+
if _, err := ws.Connect(); err != nil {
19+
return err
20+
}
21+
defer ws.Close()
22+
data, err := ws.Call("device.pair.list", map[string]any{})
23+
if err != nil {
24+
return err
25+
}
26+
if cfg.OutputFormat != "table" {
27+
printer.Print(unmarshalList(data))
28+
return nil
29+
}
30+
tbl := output.NewTable("ID", "NAME", "USER", "STATUS", "PAIRED_AT", "LAST_SEEN")
31+
for _, d := range unmarshalList(data) {
32+
tbl.AddRow(str(d, "id"), str(d, "device_name"), str(d, "user_id"),
33+
str(d, "status"), str(d, "paired_at"), str(d, "last_seen_at"))
34+
}
35+
printer.Print(tbl)
36+
return nil
37+
},
38+
}
39+
40+
var devicesRevokeCmd = &cobra.Command{
41+
Use: "revoke <id>", Short: "Revoke a paired device", Args: cobra.ExactArgs(1),
42+
RunE: func(cmd *cobra.Command, args []string) error {
43+
if !tui.Confirm("Revoke this device?", cfg.Yes) {
44+
return nil
45+
}
46+
ws, err := newWS("cli")
47+
if err != nil {
48+
return err
49+
}
50+
if _, err := ws.Connect(); err != nil {
51+
return err
52+
}
53+
defer ws.Close()
54+
_, err = ws.Call("device.pair.revoke", map[string]any{"id": args[0]})
55+
if err != nil {
56+
return err
57+
}
58+
printer.Success("Device revoked")
59+
return nil
60+
},
61+
}
62+
63+
var devicesPairingStatusCmd = &cobra.Command{
64+
Use: "pairing-status", Short: "Check browser pairing status",
65+
RunE: func(cmd *cobra.Command, args []string) error {
66+
ws, err := newWS("cli")
67+
if err != nil {
68+
return err
69+
}
70+
if _, err := ws.Connect(); err != nil {
71+
return err
72+
}
73+
defer ws.Close()
74+
data, err := ws.Call("browser.pairing.status", map[string]any{})
75+
if err != nil {
76+
return err
77+
}
78+
printer.Print(unmarshalMap(data))
79+
return nil
80+
},
81+
}
82+
83+
func init() {
84+
devicesCmd.AddCommand(devicesListCmd, devicesRevokeCmd, devicesPairingStatusCmd)
85+
rootCmd.AddCommand(devicesCmd)
86+
}

0 commit comments

Comments
 (0)