diff --git a/cmd/agents_files.go b/cmd/agents_files.go new file mode 100644 index 0000000..44aaea4 --- /dev/null +++ b/cmd/agents_files.go @@ -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 ", 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 ", 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 ", 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) +} diff --git a/cmd/agents_wake.go b/cmd/agents_wake.go new file mode 100644 index 0000000..81a1087 --- /dev/null +++ b/cmd/agents_wake.go @@ -0,0 +1,29 @@ +package cmd + +import ( + "net/url" + + "github.com/spf13/cobra" +) + +var agentsWakeCmd = &cobra.Command{ + Use: "wake ", + 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) +} diff --git a/cmd/cmd_test.go b/cmd/cmd_test.go index 69e5569..fe77109 100644 --- a/cmd/cmd_test.go +++ b/cmd/cmd_test.go @@ -28,7 +28,10 @@ func TestAllCommandsRegistered(t *testing.T) { "credentials", "cron", "delegations", + "devices", + "export", "heartbeat", + "import", "knowledge-graph", "logs", "mcp", @@ -99,7 +102,10 @@ func TestCommandUseFields(t *testing.T) { {"credentials"}, {"cron"}, {"delegations"}, + {"devices"}, + {"export"}, {"heartbeat"}, + {"import"}, {"knowledge-graph"}, {"logs"}, {"mcp"}, diff --git a/cmd/devices.go b/cmd/devices.go new file mode 100644 index 0000000..e5365c3 --- /dev/null +++ b/cmd/devices.go @@ -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 ", 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) +} diff --git a/cmd/export_import.go b/cmd/export_import.go new file mode 100644 index 0000000..a0ceeb6 --- /dev/null +++ b/cmd/export_import.go @@ -0,0 +1,373 @@ +package cmd + +import ( + "encoding/json" + "fmt" + "io" + "net/url" + "os" + + "github.com/nextlevelbuilder/goclaw-cli/internal/tui" + "github.com/spf13/cobra" +) + +var exportCmd = &cobra.Command{Use: "export", Short: "Export resources (agents, teams, skills, mcp)"} +var importCmd = &cobra.Command{Use: "import", Short: "Import resources (agents, teams, skills, mcp)"} + +// --- Agent Export/Import --- + +var exportAgentPreviewCmd = &cobra.Command{ + Use: "agent-preview ", Short: "Preview agent export", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + data, err := c.Get("/v1/agents/" + url.PathEscape(args[0]) + "/export/preview") + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +var exportAgentCmd = &cobra.Command{ + Use: "agent ", Short: "Export an agent", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + outFile, _ := cmd.Flags().GetString("output") + resp, err := c.GetRaw("/v1/agents/" + url.PathEscape(args[0]) + "/export") + if err != nil { + return err + } + defer resp.Body.Close() + return writeExportFile(resp.Body, outFile, "agent-"+args[0]+".json") + }, +} + +var importAgentPreviewCmd = &cobra.Command{ + Use: "agent-preview ", Short: "Preview agent import", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + body, err := readJSONFile(args[0]) + if err != nil { + return err + } + data, err := c.Post("/v1/agents/import/preview", body) + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +var importAgentCmd = &cobra.Command{ + Use: "agent ", Short: "Import agents from file", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + if !tui.Confirm("Import agents from "+args[0]+"?", cfg.Yes) { + return nil + } + c, err := newHTTP() + if err != nil { + return err + } + body, err := readJSONFile(args[0]) + if err != nil { + return err + } + data, err := c.Post("/v1/agents/import", body) + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +// --- Team Export/Import --- + +var exportTeamPreviewCmd = &cobra.Command{ + Use: "team-preview ", Short: "Preview team export", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + data, err := c.Get("/v1/teams/" + url.PathEscape(args[0]) + "/export/preview") + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +var exportTeamCmd = &cobra.Command{ + Use: "team ", Short: "Export a team", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + outFile, _ := cmd.Flags().GetString("output") + resp, err := c.GetRaw("/v1/teams/" + url.PathEscape(args[0]) + "/export") + if err != nil { + return err + } + defer resp.Body.Close() + return writeExportFile(resp.Body, outFile, "team-"+args[0]+".json") + }, +} + +var importTeamPreviewCmd = &cobra.Command{ + Use: "team-preview ", Short: "Preview team import", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + body, err := readJSONFile(args[0]) + if err != nil { + return err + } + data, err := c.Post("/v1/teams/import/preview", body) + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +var importTeamCmd = &cobra.Command{ + Use: "team ", Short: "Import team from file", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + if !tui.Confirm("Import team from "+args[0]+"?", cfg.Yes) { + return nil + } + c, err := newHTTP() + if err != nil { + return err + } + body, err := readJSONFile(args[0]) + if err != nil { + return err + } + data, err := c.Post("/v1/teams/import", body) + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +// --- Skills Export/Import --- + +var exportSkillsPreviewCmd = &cobra.Command{ + Use: "skills-preview", Short: "Preview skills export", + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + data, err := c.Get("/v1/skills/export/preview") + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +var exportSkillsCmd = &cobra.Command{ + Use: "skills", Short: "Export skills", + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + outFile, _ := cmd.Flags().GetString("output") + resp, err := c.GetRaw("/v1/skills/export") + if err != nil { + return err + } + defer resp.Body.Close() + return writeExportFile(resp.Body, outFile, "skills-export.json") + }, +} + +var importSkillsPreviewCmd = &cobra.Command{ + Use: "skills-preview ", Short: "Preview skills import", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + body, err := readJSONFile(args[0]) + if err != nil { + return err + } + data, err := c.Post("/v1/skills/import/preview", body) + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +var importSkillsCmd = &cobra.Command{ + Use: "skills ", Short: "Import skills from file", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + if !tui.Confirm("Import skills from "+args[0]+"?", cfg.Yes) { + return nil + } + c, err := newHTTP() + if err != nil { + return err + } + body, err := readJSONFile(args[0]) + if err != nil { + return err + } + data, err := c.Post("/v1/skills/import", body) + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +// --- MCP Export/Import --- + +var exportMCPPreviewCmd = &cobra.Command{ + Use: "mcp-preview", Short: "Preview MCP servers export", + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + data, err := c.Get("/v1/mcp/export/preview") + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +var exportMCPCmd = &cobra.Command{ + Use: "mcp", Short: "Export MCP servers", + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + outFile, _ := cmd.Flags().GetString("output") + resp, err := c.GetRaw("/v1/mcp/export") + if err != nil { + return err + } + defer resp.Body.Close() + return writeExportFile(resp.Body, outFile, "mcp-export.json") + }, +} + +var importMCPPreviewCmd = &cobra.Command{ + Use: "mcp-preview ", Short: "Preview MCP servers import", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + body, err := readJSONFile(args[0]) + if err != nil { + return err + } + data, err := c.Post("/v1/mcp/import/preview", body) + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +var importMCPCmd = &cobra.Command{ + Use: "mcp ", Short: "Import MCP servers from file", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + if !tui.Confirm("Import MCP servers from "+args[0]+"?", cfg.Yes) { + return nil + } + c, err := newHTTP() + if err != nil { + return err + } + body, err := readJSONFile(args[0]) + if err != nil { + return err + } + data, err := c.Post("/v1/mcp/import", body) + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +// writeExportFile saves response body to a file. +func writeExportFile(body io.Reader, outFile, defaultName string) error { + if outFile == "" { + outFile = defaultName + } + f, err := os.Create(outFile) + if err != nil { + return err + } + n, err := io.Copy(f, body) + if err != nil { + f.Close() + return err + } + if err := f.Close(); err != nil { + return fmt.Errorf("close export file: %w", err) + } + printer.Success(fmt.Sprintf("Exported %d bytes to %s", n, outFile)) + return nil +} + +// readJSONFile reads and parses a JSON file. +func readJSONFile(path string) (any, error) { + data, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("read file: %w", err) + } + var body any + if err := json.Unmarshal(data, &body); err != nil { + return nil, fmt.Errorf("invalid JSON: %w", err) + } + return body, nil +} + +func init() { + for _, c := range []*cobra.Command{exportAgentCmd, exportTeamCmd, exportSkillsCmd, exportMCPCmd} { + c.Flags().StringP("output", "o", "", "Output file path") + } + + exportCmd.AddCommand(exportAgentPreviewCmd, exportAgentCmd, exportTeamPreviewCmd, exportTeamCmd, + exportSkillsPreviewCmd, exportSkillsCmd, exportMCPPreviewCmd, exportMCPCmd) + importCmd.AddCommand(importAgentPreviewCmd, importAgentCmd, importTeamPreviewCmd, importTeamCmd, + importSkillsPreviewCmd, importSkillsCmd, importMCPPreviewCmd, importMCPCmd) + rootCmd.AddCommand(exportCmd, importCmd) +} diff --git a/cmd/knowledge_graph_dedup.go b/cmd/knowledge_graph_dedup.go new file mode 100644 index 0000000..58b9f84 --- /dev/null +++ b/cmd/knowledge_graph_dedup.go @@ -0,0 +1,103 @@ +package cmd + +import ( + "net/url" + + "github.com/nextlevelbuilder/goclaw-cli/internal/output" + "github.com/nextlevelbuilder/goclaw-cli/internal/tui" + "github.com/spf13/cobra" +) + +var kgDedupCmd = &cobra.Command{Use: "dedup", Short: "Manage entity deduplication"} + +var kgDedupScanCmd = &cobra.Command{ + Use: "scan ", Short: "Scan for duplicate entities", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + data, err := c.Post("/v1/agents/"+url.PathEscape(args[0])+"/kg/dedup/scan", nil) + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +var kgDedupListCmd = &cobra.Command{ + Use: "list ", Short: "List duplicate candidates", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + data, err := c.Get("/v1/agents/" + url.PathEscape(args[0]) + "/kg/dedup") + if err != nil { + return err + } + if cfg.OutputFormat != "table" { + printer.Print(unmarshalList(data)) + return nil + } + tbl := output.NewTable("ID", "ENTITY_A", "ENTITY_B", "SCORE") + for _, r := range unmarshalList(data) { + tbl.AddRow(str(r, "id"), str(r, "entity_a"), str(r, "entity_b"), str(r, "score")) + } + printer.Print(tbl) + return nil + }, +} + +var kgDedupDismissCmd = &cobra.Command{ + Use: "dismiss ", Short: "Dismiss duplicate suggestion", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + ids, _ := cmd.Flags().GetStringSlice("ids") + data, err := c.Post("/v1/agents/"+url.PathEscape(args[0])+"/kg/dedup/dismiss", + map[string]any{"ids": ids}) + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +var kgMergeCmd = &cobra.Command{ + Use: "merge ", Short: "Merge KG entities", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + if !tui.Confirm("Merge these KG entities?", cfg.Yes) { + return nil + } + c, err := newHTTP() + if err != nil { + return err + } + source, _ := cmd.Flags().GetString("source") + target, _ := cmd.Flags().GetString("target") + data, err := c.Post("/v1/agents/"+url.PathEscape(args[0])+"/kg/merge", + buildBody("source_id", source, "target_id", target)) + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +func init() { + kgDedupDismissCmd.Flags().StringSlice("ids", nil, "Duplicate pair IDs (comma-separated or repeated)") + _ = kgDedupDismissCmd.MarkFlagRequired("ids") + kgMergeCmd.Flags().String("source", "", "Source entity ID") + kgMergeCmd.Flags().String("target", "", "Target entity ID") + _ = kgMergeCmd.MarkFlagRequired("source") + _ = kgMergeCmd.MarkFlagRequired("target") + + kgDedupCmd.AddCommand(kgDedupScanCmd, kgDedupListCmd, kgDedupDismissCmd) + kgCmd.AddCommand(kgDedupCmd, kgMergeCmd) +} diff --git a/cmd/mcp_reconnect.go b/cmd/mcp_reconnect.go new file mode 100644 index 0000000..d5d732f --- /dev/null +++ b/cmd/mcp_reconnect.go @@ -0,0 +1,27 @@ +package cmd + +import ( + "net/url" + + "github.com/spf13/cobra" +) + +var mcpServersReconnectCmd = &cobra.Command{ + Use: "reconnect ", Short: "Reconnect MCP server", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + _, err = c.Post("/v1/mcp/servers/"+url.PathEscape(args[0])+"/reconnect", nil) + if err != nil { + return err + } + printer.Success("MCP server reconnect triggered") + return nil + }, +} + +func init() { + mcpServersCmd.AddCommand(mcpServersReconnectCmd) +} diff --git a/cmd/memory_index.go b/cmd/memory_index.go new file mode 100644 index 0000000..a24b0bf --- /dev/null +++ b/cmd/memory_index.go @@ -0,0 +1,69 @@ +package cmd + +import ( + "net/url" + + "github.com/nextlevelbuilder/goclaw-cli/internal/output" + "github.com/spf13/cobra" +) + +var memoryIndexCmd = &cobra.Command{ + Use: "index ", Short: "Index a memory document", Args: cobra.ExactArgs(2), + 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])+"/memory/index", + map[string]any{"path": args[1]}) + if err != nil { + return err + } + printer.Success("Document indexed") + return nil + }, +} + +var memoryIndexAllCmd = &cobra.Command{ + Use: "index-all ", Short: "Index all memory documents", 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])+"/memory/index-all", nil) + if err != nil { + return err + } + printer.Success("All documents indexed") + return nil + }, +} + +var memoryChunksCmd = &cobra.Command{ + Use: "chunks ", Short: "List memory chunks", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + data, err := c.Get("/v1/agents/" + url.PathEscape(args[0]) + "/memory/chunks") + if err != nil { + return err + } + if cfg.OutputFormat != "table" { + printer.Print(unmarshalList(data)) + return nil + } + tbl := output.NewTable("ID", "DOCUMENT", "SIZE", "CREATED") + for _, ch := range unmarshalList(data) { + tbl.AddRow(str(ch, "id"), str(ch, "document_path"), str(ch, "size"), str(ch, "created_at")) + } + printer.Print(tbl) + return nil + }, +} + +func init() { + memoryCmd.AddCommand(memoryIndexCmd, memoryIndexAllCmd, memoryChunksCmd) +} diff --git a/cmd/providers_verify_embedding.go b/cmd/providers_verify_embedding.go new file mode 100644 index 0000000..f7d6019 --- /dev/null +++ b/cmd/providers_verify_embedding.go @@ -0,0 +1,27 @@ +package cmd + +import ( + "net/url" + + "github.com/spf13/cobra" +) + +var providersVerifyEmbeddingCmd = &cobra.Command{ + Use: "verify-embedding ", Short: "Verify embedding API credentials", Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + c, err := newHTTP() + if err != nil { + return err + } + data, err := c.Post("/v1/providers/"+url.PathEscape(args[0])+"/verify-embedding", nil) + if err != nil { + return err + } + printer.Print(unmarshalMap(data)) + return nil + }, +} + +func init() { + providersCmd.AddCommand(providersVerifyEmbeddingCmd) +} diff --git a/cmd/teams_tasks_delete.go b/cmd/teams_tasks_delete.go new file mode 100644 index 0000000..51f2b22 --- /dev/null +++ b/cmd/teams_tasks_delete.go @@ -0,0 +1,35 @@ +package cmd + +import ( + "github.com/nextlevelbuilder/goclaw-cli/internal/tui" + "github.com/spf13/cobra" +) + +var teamsTasksDeleteCmd = &cobra.Command{ + Use: "delete ", Short: "Delete a task", Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + if !tui.Confirm("Delete this task?", 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("teams.tasks.delete", map[string]any{ + "team_id": args[0], "task_id": args[1], + }) + if err != nil { + return err + } + printer.Success("Task deleted") + return nil + }, +} + +func init() { + teamsTasksCmd.AddCommand(teamsTasksDeleteCmd) +}