From 0062d5c2a28752f8c1bcef3a0acd2c027ef03203 Mon Sep 17 00:00:00 2001 From: Craig Jellick Date: Thu, 11 Dec 2025 10:33:31 -0700 Subject: [PATCH] WIP: Delete a bunch of stuff from the cli Signed-off-by: Craig Jellick --- pkg/cli/agents.go | 61 ------ pkg/cli/catalog.go | 60 ------ pkg/cli/create.go | 174 ------------------ pkg/cli/credentials.go | 78 -------- pkg/cli/credentials_delete.go | 45 ----- pkg/cli/edit.go | 96 ---------- pkg/cli/edit/edit.go | 73 -------- pkg/cli/invoke.go | 55 ------ pkg/cli/invokeclient/input.go | 40 ---- pkg/cli/invokeclient/invoke.go | 88 --------- pkg/cli/{obots.go => projects.go} | 13 +- .../{obots_create.go => projects_create.go} | 32 ++-- pkg/cli/{obots_rm.go => projects_rm.go} | 22 +-- pkg/cli/rm.go | 70 ------- pkg/cli/root.go | 20 +- pkg/cli/tools.go | 67 ------- pkg/cli/tools_register.go | 36 ---- pkg/cli/tools_unregister.go | 32 ---- pkg/cli/tools_update.go | 30 --- pkg/cli/update.go | 63 ------- 20 files changed, 37 insertions(+), 1118 deletions(-) delete mode 100644 pkg/cli/agents.go delete mode 100644 pkg/cli/catalog.go delete mode 100644 pkg/cli/create.go delete mode 100644 pkg/cli/credentials.go delete mode 100644 pkg/cli/credentials_delete.go delete mode 100644 pkg/cli/edit.go delete mode 100644 pkg/cli/edit/edit.go delete mode 100644 pkg/cli/invoke.go delete mode 100644 pkg/cli/invokeclient/input.go delete mode 100644 pkg/cli/invokeclient/invoke.go rename pkg/cli/{obots.go => projects.go} (77%) rename pkg/cli/{obots_create.go => projects_create.go} (75%) rename pkg/cli/{obots_rm.go => projects_rm.go} (70%) delete mode 100644 pkg/cli/rm.go delete mode 100644 pkg/cli/tools.go delete mode 100644 pkg/cli/tools_register.go delete mode 100644 pkg/cli/tools_unregister.go delete mode 100644 pkg/cli/tools_update.go delete mode 100644 pkg/cli/update.go diff --git a/pkg/cli/agents.go b/pkg/cli/agents.go deleted file mode 100644 index 9186484664..0000000000 --- a/pkg/cli/agents.go +++ /dev/null @@ -1,61 +0,0 @@ -package cli - -import ( - "fmt" - - "github.com/dustin/go-humanize" - "github.com/obot-platform/obot/apiclient" - "github.com/obot-platform/obot/apiclient/types" - "github.com/spf13/cobra" -) - -type Agents struct { - root *Obot - Quiet bool `usage:"Only print IDs of agents" short:"q"` - Wide bool `usage:"Print more information" short:"w"` - Output string `usage:"Output format (table, json, yaml)" short:"o" default:"table"` -} - -func (l *Agents) Customize(cmd *cobra.Command) { - cmd.Aliases = []string{"agent", "a"} -} - -func (l *Agents) Run(cmd *cobra.Command, args []string) error { - var ( - agents types.AgentList - err error - ) - - if len(args) > 0 { - for _, arg := range args { - agent, err := l.root.Client.GetAgent(cmd.Context(), arg) - if err != nil { - return err - } - agents.Items = append(agents.Items, *agent) - } - } else { - agents, err = l.root.Client.ListAgents(cmd.Context(), apiclient.ListAgentsOptions{}) - if err != nil { - return err - } - } - - if ok, err := output(l.Output, agents); ok || err != nil { - return err - } - - if l.Quiet { - for _, agent := range agents.Items { - fmt.Println(agent.ID) - } - return nil - } - - w := newTable("ID", "NAME", "DESCRIPTION", "INVOKE", "CREATED") - for _, agent := range agents.Items { - w.WriteRow(agent.ID, agent.Name, truncate(agent.Description, l.Wide), agent.Links["invoke"], humanize.Time(agent.Created.Time)) - } - - return w.Err() -} diff --git a/pkg/cli/catalog.go b/pkg/cli/catalog.go deleted file mode 100644 index 9923d6c72f..0000000000 --- a/pkg/cli/catalog.go +++ /dev/null @@ -1,60 +0,0 @@ -package cli - -import ( - "fmt" - - "github.com/dustin/go-humanize" - "github.com/spf13/cobra" -) - -// Catalog implements the 'obot catalog' command -type Catalog struct { - root *Obot - Quiet bool `usage:"Only print IDs of catalog obots" short:"q"` - Wide bool `usage:"Print more information" short:"w"` - Output string `usage:"Output format (table, json, yaml)" short:"o" default:"table"` -} - -func (l *Catalog) Customize(cmd *cobra.Command) { - cmd.Use = "catalog [flags]" - cmd.Short = "Lists obots from the catalog" - cmd.Long = "Lists all obots from the catalog (shared obots)" - cmd.Aliases = []string{"cat", "c"} -} - -func (l *Catalog) Run(cmd *cobra.Command, _ []string) error { - shares, err := l.root.Client.ListProjectShares(cmd.Context()) - if err != nil { - return err - } - - if ok, err := output(l.Output, shares); ok || err != nil { - return err - } - - if l.Quiet { - for _, share := range shares.Items { - fmt.Println(share.PublicID) - } - return nil - } - - w := newTable("ID", "NAME", "DESCRIPTION", "FEATURED", "PROJECT_ID", "CREATED") - for _, share := range shares.Items { - featured := "No" - if share.Featured { - featured = "Yes" - } - - w.WriteRow( - share.PublicID, - share.Name, - truncate(share.Description, l.Wide), - featured, - share.ProjectID, - humanize.Time(share.Created.Time), - ) - } - - return w.Err() -} diff --git a/pkg/cli/create.go b/pkg/cli/create.go deleted file mode 100644 index daed140b3f..0000000000 --- a/pkg/cli/create.go +++ /dev/null @@ -1,174 +0,0 @@ -package cli - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "os" - "strings" - "time" - - "github.com/obot-platform/namegenerator" - "github.com/obot-platform/obot/pkg/cli/edit" - "github.com/obot-platform/obot/pkg/cli/templates" - "github.com/pterm/pterm" - "github.com/spf13/cobra" - "golang.org/x/text/cases" - "golang.org/x/text/language" - yamlv3 "gopkg.in/yaml.v3" -) - -type Create struct { - Quiet bool `usage:"Only print ID after successful creation." short:"q"` - root *Obot -} - -func (l *Create) Customize(cmd *cobra.Command) { - cmd.Use = "create [flags] FILE" -} - -type manifest struct { - Type string - Data []byte -} - -func parseManifests(data []byte) (result []manifest, _ error) { - var ( - dec = yamlv3.NewDecoder(bytes.NewReader(data)) - ) - for { - parsed := map[string]any{} - if err := dec.Decode(&parsed); err != nil { - if err == io.EOF { - break - } - return nil, err - } - - var typeName string - for k, v := range parsed { - if strings.EqualFold(k, "type") { - typeName, _ = v.(string) - if typeName != "" { - break - } - } - } - - if typeName == "" { - return nil, fmt.Errorf("missing type field in manifest") - } - - jsonData, err := json.Marshal(parsed) - if err != nil { - return nil, err - } - - result = append(result, manifest{ - Type: typeName, - Data: jsonData, - }) - } - - return -} - -func readInput(file string) (io.ReadCloser, error) { - if strings.HasPrefix(file, "http://") || strings.HasPrefix(file, "https://") { - resp, err := http.Get(file) - if err != nil { - return nil, err - } - return resp.Body, nil - } - - return os.Open(file) -} - -func (l *Create) create(ctx context.Context, input io.ReadCloser) error { - defer input.Close() - - data, err := io.ReadAll(input) - if err != nil { - return err - } - - manifests, err := parseManifests(data) - if err != nil { - return fmt.Errorf("failed to parse manifest: %v", err) - } - - for _, manifest := range manifests { - id, err := l.root.Client.Create(ctx, manifest.Type, manifest.Data) - if err != nil { - return err - } - if l.Quiet { - fmt.Println(id) - } else { - fmt.Printf("Created %s: %s\n", manifest.Type, id) - } - } - - return nil -} - -func newName() string { - caser := cases.Title(language.English) - return caser.String(strings.ReplaceAll(namegenerator.NewNameGenerator(time.Now().UnixNano()).Generate(), "-", " ")) -} - -func (l *Create) fromTemplate() (string, error) { - sel, err := pterm.DefaultInteractiveSelect. - WithDefaultText("Select a type to create"). - WithOptions([]string{ - "Agent", - "Workflow", - "Webhook", - "Email Receiver", - }).Show() - if err != nil { - return "", err - } - - template, err := templates.FS.ReadFile(strings.ToLower(strings.ReplaceAll(sel, " ", "") + ".yaml")) - if err != nil { - return "", err - } - - template = bytes.ReplaceAll(template, []byte("%NAME%"), []byte(newName())) - - err = edit.Edit(template, ".yaml", func(data []byte) error { - template = data - return nil - }) - if errors.Is(err, edit.ErrEditAborted) { - return string(template), nil - } - - return string(template), err -} - -func (l *Create) Run(cmd *cobra.Command, args []string) error { - var input io.ReadCloser - - if len(args) == 0 { - template, err := l.fromTemplate() - if err != nil { - return err - } - input = io.NopCloser(strings.NewReader(template)) - } else { - var err error - input, err = readInput(args[0]) - if err != nil { - return err - } - } - - return l.create(cmd.Context(), input) -} diff --git a/pkg/cli/credentials.go b/pkg/cli/credentials.go deleted file mode 100644 index 89ec073f9c..0000000000 --- a/pkg/cli/credentials.go +++ /dev/null @@ -1,78 +0,0 @@ -package cli - -import ( - "fmt" - "strings" - - "github.com/dustin/go-humanize" - "github.com/obot-platform/obot/apiclient" - "github.com/obot-platform/obot/apiclient/types" - "github.com/spf13/cobra" -) - -type Credentials struct { - root *Obot - Wide bool `usage:"Print more information" short:"w"` - Quiet bool `usage:"Only print IDs of credentials" short:"q"` - ThreadID string `usage:"Specific thread list credentials for" short:"t"` -} - -func (l *Credentials) Customize(cmd *cobra.Command) { - cmd.Use = "credentials [flags]" - cmd.Aliases = []string{"credential", "cred", "creds", "c"} -} - -func (l *Credentials) printCredentialsQuiet(i types.CredentialList) error { - for _, credential := range i.Items { - fmt.Println(credential.Name) - } - return nil -} - -func (l *Credentials) printCredentials(i types.CredentialList) error { - w := newTable("NAME", "ENV", "EXPIRES") - for _, credential := range i.Items { - time := "never" - if credential.ExpiresAt != nil { - time = humanize.Time(credential.ExpiresAt.Time) - } - w.WriteRow(credential.Name, strings.Join(credential.EnvVars, ","), time) - } - - return w.Err() -} - -func (l *Credentials) Run(cmd *cobra.Command, _ []string) error { - creds, err := l.root.Client.ListCredentials(cmd.Context(), apiclient.ListCredentialsOptions{ - ThreadID: l.ThreadID, - }) - if err != nil { - return err - } - - if l.ThreadID == "" { - agents, err := l.root.Client.ListAgents(cmd.Context(), apiclient.ListAgentsOptions{}) - if err != nil { - return err - } - - for _, agent := range agents.Items { - agentCreds, err := l.root.Client.ListCredentials(cmd.Context(), apiclient.ListCredentialsOptions{ - AgentID: agent.ID, - }) - if err != nil { - return err - } - for _, cred := range agentCreds.Items { - cred.Name = fmt.Sprintf("%s::%s", agent.ID, cred.Name) - creds.Items = append(creds.Items, cred) - } - } - } - - if l.Quiet { - return l.printCredentialsQuiet(creds) - } - - return l.printCredentials(creds) -} diff --git a/pkg/cli/credentials_delete.go b/pkg/cli/credentials_delete.go deleted file mode 100644 index 7dec38b3b3..0000000000 --- a/pkg/cli/credentials_delete.go +++ /dev/null @@ -1,45 +0,0 @@ -package cli - -import ( - "fmt" - "strings" - - "github.com/obot-platform/obot/apiclient" - "github.com/obot-platform/obot/pkg/system" - "github.com/spf13/cobra" -) - -type CredentialsDelete struct { - root *Obot - Quiet bool `usage:"Only print IDs of credentials" short:"q"` -} - -func (l *CredentialsDelete) Customize(cmd *cobra.Command) { - cmd.Use = "delete [flags] [CRED_NAME...]" - cmd.Aliases = []string{"rm", "del", "d"} -} - -func (l *CredentialsDelete) Run(cmd *cobra.Command, args []string) error { - for _, arg := range args { - opt := apiclient.DeleteCredentialsOptions{} - scope, name, ok := strings.Cut(arg, "::") - if !ok { - name = scope - } else if system.IsThreadID(scope) { - opt.ThreadID = scope - } else if system.IsAgentID(scope) { - opt.AgentID = scope - } else if system.IsWorkflowID(scope) { - opt.WorkflowID = scope - } - if err := l.root.Client.DeleteCredential(cmd.Context(), name, opt); err != nil { - return err - } - if l.Quiet { - fmt.Println(name) - } else { - fmt.Printf("Credential %s deleted\n", name) - } - } - return nil -} diff --git a/pkg/cli/edit.go b/pkg/cli/edit.go deleted file mode 100644 index ea87e41235..0000000000 --- a/pkg/cli/edit.go +++ /dev/null @@ -1,96 +0,0 @@ -package cli - -import ( - "context" - "fmt" - - "github.com/obot-platform/obot/apiclient/types" - "github.com/obot-platform/obot/pkg/cli/edit" - "github.com/obot-platform/obot/pkg/system" - "github.com/spf13/cobra" - "sigs.k8s.io/yaml" -) - -type Edit struct { - root *Obot - Prompt bool `usage:"Edit just the prompt for the agent" short:"p"` -} - -func (l *Edit) Customize(cmd *cobra.Command) { - cmd.Args = cobra.ExactArgs(1) -} - -func (l *Edit) Run(cmd *cobra.Command, args []string) error { - id := args[0] - if system.IsAgentID(id) { - return l.editAgent(cmd.Context(), id) - } - return l.editWorkflow(cmd.Context(), id) -} - -func (l *Edit) editWorkflow(ctx context.Context, id string) error { - workflow, err := l.root.Client.GetWorkflow(ctx, id) - if err != nil { - return err - } - - data, err := yaml.Marshal(workflow.WorkflowManifest) - if err != nil { - return err - } - - err = edit.Edit(data, ".yaml", func(data []byte) error { - var newManifest types.WorkflowManifest - if err := yaml.Unmarshal(data, &newManifest); err != nil { - return err - } - - _, err := l.root.Client.UpdateWorkflow(ctx, workflow.ID, newManifest) - return err - }) - if err != nil { - return err - } - fmt.Printf("Workflow updated: %s\n", workflow.ID) - return nil -} - -func (l *Edit) editAgent(ctx context.Context, id string) error { - agent, err := l.root.Client.GetAgent(ctx, id) - if err != nil { - return err - } - - if l.Prompt { - err = edit.Edit([]byte(agent.Prompt), ".txt", func(data []byte) error { - agent.Prompt = string(data) - _, err := l.root.Client.UpdateAgent(ctx, agent.ID, agent.AgentManifest) - return err - }) - if err != nil { - return err - } - fmt.Printf("Agent updated: %s\n", agent.ID) - return nil - } - - data, err := yaml.Marshal(agent.AgentManifest) - if err != nil { - return err - } - - err = edit.Edit(data, ".yaml", func(data []byte) error { - var newManifest types.AgentManifest - if err := yaml.Unmarshal(data, &newManifest); err != nil { - return err - } - - _, err := l.root.Client.UpdateAgent(ctx, agent.ID, newManifest) - return err - }) - if err != nil { - return err - } - fmt.Printf("Agent updated: %s\n", agent.ID) - return nil -} diff --git a/pkg/cli/edit/edit.go b/pkg/cli/edit/edit.go deleted file mode 100644 index 6f3cb0c798..0000000000 --- a/pkg/cli/edit/edit.go +++ /dev/null @@ -1,73 +0,0 @@ -package edit - -import ( - "bytes" - "errors" - "os" - "strings" - - "k8s.io/kubectl/pkg/cmd/util/editor" -) - -var ( - envs = []string{ - "OBOT_EDITOR", - "EDITOR", - } -) - -func stripComments(buf []byte) []byte { - var ( - result = bytes.Buffer{} - start = true - ) - for line := range strings.SplitSeq(string(buf), "\n") { - if start { - if strings.HasPrefix(line, "# ") { - continue - } - start = false - } - result.WriteString(line) - result.WriteString("\n") - } - return result.Bytes() -} - -func commentError(err error, buf []byte) []byte { - var header bytes.Buffer - for line := range strings.SplitSeq(strings.ReplaceAll(err.Error(), "\r", ""), "\n") { - header.WriteString("# ") - header.WriteString(line) - header.WriteString("\n") - } - return append(header.Bytes(), buf...) -} - -var ErrEditAborted = errors.New("edit aborted") - -func Edit(content []byte, suffix string, save func([]byte) error) error { - editor := editor.NewDefaultEditor(envs) - for { - buf, file, err := editor.LaunchTempFile("obot", suffix, bytes.NewReader(content)) - if file != "" { - _ = os.Remove(file) - } - if err != nil { - return err - } - - if bytes.Equal(buf, content) { - return ErrEditAborted - } - - buf = stripComments(buf) - - if err := save(buf); err != nil { - content = commentError(err, buf) - continue - } - - return nil - } -} diff --git a/pkg/cli/invoke.go b/pkg/cli/invoke.go deleted file mode 100644 index 851bc0546e..0000000000 --- a/pkg/cli/invoke.go +++ /dev/null @@ -1,55 +0,0 @@ -package cli - -import ( - "fmt" - "os" - "strings" - - "github.com/obot-platform/obot/pkg/cli/invokeclient" - "github.com/obot-platform/obot/pkg/system" - "github.com/spf13/cobra" - "golang.org/x/term" -) - -type Invoke struct { - Thread string `usage:"Thread name to run the agent in." short:"t"` - Step string `usage:"Workflow step to rerun from, thread is already required" short:"s"` - Quiet *bool `usage:"Only print output characters" short:"q"` - Verbose bool `usage:"Print more information" short:"v"` - Async bool `usage:"Run the agent asynchronously" short:"a"` - root *Obot -} - -func (l *Invoke) GetQuiet() bool { - if l.Quiet == nil { - return false - } - return *l.Quiet -} - -func (l *Invoke) Pre(*cobra.Command, []string) error { - if l.Quiet == nil && term.IsTerminal(int(os.Stdout.Fd())) { - l.Quiet = new(bool) - } - return nil -} - -func (l *Invoke) Customize(cmd *cobra.Command) { - cmd.Use = "invoke [flags] AGENT [INPUT...]" - cmd.Args = cobra.MinimumNArgs(1) - cmd.Flags().SetInterspersed(false) -} - -func (l *Invoke) Run(cmd *cobra.Command, args []string) error { - if l.Step != "" && l.Thread == "" && !system.IsThreadID(args[0]) { - return fmt.Errorf("thread is required when rerunning a step") - } - - return invokeclient.Invoke(cmd.Context(), l.root.Client, args[0], strings.Join(args[1:], " "), invokeclient.Options{ - ThreadID: l.Thread, - Quiet: l.GetQuiet(), - Details: l.Verbose, - Async: l.Async, - Step: l.Step, - }) -} diff --git a/pkg/cli/invokeclient/input.go b/pkg/cli/invokeclient/input.go deleted file mode 100644 index f5ee561ead..0000000000 --- a/pkg/cli/invokeclient/input.go +++ /dev/null @@ -1,40 +0,0 @@ -package invokeclient - -import ( - "github.com/obot-platform/obot/apiclient" - "github.com/obot-platform/obot/apiclient/types" - "github.com/obot-platform/obot/pkg/cli/textio" -) - -type QuietInputter struct { -} - -func (d QuietInputter) Next(previous string, resp *types.InvokeResponse) (string, bool, error) { - if resp == nil { - return previous, true, nil - } - return "", false, nil -} - -type VerboseInputter struct { - client *apiclient.Client -} - -func nextInput() (string, bool, error) { - x, err := textio.Ask("Input", "") - if err != nil { - return "", false, err - } - return x, true, nil -} - -func (d VerboseInputter) Next(previous string, resp *types.InvokeResponse) (string, bool, error) { - if resp == nil { - if previous == "" { - return nextInput() - } - return previous, true, nil - } - - return nextInput() -} diff --git a/pkg/cli/invokeclient/invoke.go b/pkg/cli/invokeclient/invoke.go deleted file mode 100644 index c7e71a6cf5..0000000000 --- a/pkg/cli/invokeclient/invoke.go +++ /dev/null @@ -1,88 +0,0 @@ -package invokeclient - -import ( - "context" - "fmt" - - "github.com/obot-platform/obot/apiclient" - "github.com/obot-platform/obot/apiclient/types" - "github.com/obot-platform/obot/pkg/cli/events" - "github.com/obot-platform/obot/pkg/system" -) - -type inputter interface { - Next(previous string, resp *types.InvokeResponse) (string, bool, error) -} - -type Options struct { - ThreadID string - Quiet bool - Details bool - Async bool - Step string -} - -func Invoke(ctx context.Context, c *apiclient.Client, id, input string, opts Options) (err error) { - var ( - printer = events.NewPrinter(ctx, c, opts.Quiet, opts.Details) - inputter inputter = VerboseInputter{ - client: c, - } - threadID = opts.ThreadID - ) - if opts.Quiet { - inputter = QuietInputter{} - } - - if !system.IsWorkflowID(id) { - var ok bool - input, ok, err = inputter.Next(input, nil) - if err != nil { - return err - } - if !ok { - return fmt.Errorf("no input provided") - } - } - - for { - resp, err := c.Invoke(ctx, id, input, apiclient.InvokeOptions{ - ThreadID: threadID, - Async: opts.Async, - WorkflowStepID: opts.Step, - }) - if err != nil { - return err - } - - threadID = resp.ThreadID - - if opts.Async { - if opts.Quiet { - fmt.Println(threadID) - } else { - fmt.Printf("Thread ID: %s\n", threadID) - } - return nil - } - - if err := printer.Print(resp.Events); err != nil { - return err - } - - if system.IsWorkflowID(id) { - return nil - } - - nextInput, cont, err := inputter.Next(input, resp) - if err != nil { - return err - } else if !cont { - break - } - - input = nextInput - } - - return nil -} diff --git a/pkg/cli/obots.go b/pkg/cli/projects.go similarity index 77% rename from pkg/cli/obots.go rename to pkg/cli/projects.go index 05afcdc45b..9185e27b70 100644 --- a/pkg/cli/obots.go +++ b/pkg/cli/projects.go @@ -1,4 +1,3 @@ -// filepath: /Users/wmaxwell/code/obot-platform/obot/pkg/cli/obots.go package cli import ( @@ -10,19 +9,19 @@ import ( "github.com/spf13/cobra" ) -type Obots struct { +type Projects struct { root *Obot - Quiet bool `usage:"Only print IDs of obots" short:"q"` + Quiet bool `usage:"Only print IDs of projects" short:"q"` Wide bool `usage:"Print more information" short:"w"` Output string `usage:"Output format (table, json, yaml)" short:"o" default:"table"` - All bool `usage:"List all obots (admin only)" short:"a"` + All bool `usage:"List all projects (admin only)" short:"a"` } -func (l *Obots) Customize(cmd *cobra.Command) { - cmd.Aliases = []string{"obot", "o"} +func (l *Projects) Customize(cmd *cobra.Command) { + cmd.Aliases = []string{"project", "p"} } -func (l *Obots) Run(cmd *cobra.Command, args []string) error { +func (l *Projects) Run(cmd *cobra.Command, args []string) error { var ( projects types.ProjectList err error diff --git a/pkg/cli/obots_create.go b/pkg/cli/projects_create.go similarity index 75% rename from pkg/cli/obots_create.go rename to pkg/cli/projects_create.go index 44cb3636cf..078ffec3d9 100644 --- a/pkg/cli/obots_create.go +++ b/pkg/cli/projects_create.go @@ -8,31 +8,31 @@ import ( "github.com/spf13/cobra" ) -// CreateObot implements the 'obot obot create' subcommand -type CreateObot struct { +// CreateProject implements the 'obot projects create' subcommand +type CreateProject struct { root *Obot - CatalogID string `usage:"ID of the base agent (catalog) to use for creating the obot" short:"c"` - Name string `usage:"Name for the new obot" short:"n"` - ObotID string `usage:"ID of an existing obot to copy directly" short:"i"` + CatalogID string `usage:"ID of the base agent (catalog) to use for creating the project" short:"c"` + Name string `usage:"Name for the new project" short:"n"` + ProjectID string `usage:"ID of an existing project to copy directly" short:"i"` } -func (c *CreateObot) Customize(cmd *cobra.Command) { +func (c *CreateProject) Customize(cmd *cobra.Command) { cmd.Use = "create [flags]" - cmd.Short = "Create a new obot" - cmd.Long = "Create a new obot based on a specific agent, existing obot, or the default agent" + cmd.Short = "Create a new project" + cmd.Long = "Create a new project based on a specific agent, existing project, or the default agent" } -func (c *CreateObot) Run(cmd *cobra.Command, _ []string) error { +func (c *CreateProject) Run(cmd *cobra.Command, _ []string) error { var ( assistantID string project *types.Project err error ) - // If obot-id is provided, directly copy the specified obot - if c.ObotID != "" { + // If project-id is provided, directly copy the specified project + if c.ProjectID != "" { // Try to get project details to determine the assistant ID - projectInfo, err := c.root.Client.GetProject(cmd.Context(), c.ObotID) + projectInfo, err := c.root.Client.GetProject(cmd.Context(), c.ProjectID) if err != nil { return fmt.Errorf("failed to get project details: %w", err) } @@ -40,9 +40,9 @@ func (c *CreateObot) Run(cmd *cobra.Command, _ []string) error { assistantID = projectInfo.AssistantID // Directly copy the project - project, err = c.root.Client.CopyProject(cmd.Context(), assistantID, c.ObotID) + project, err = c.root.Client.CopyProject(cmd.Context(), assistantID, c.ProjectID) if err != nil { - return fmt.Errorf("failed to copy obot %s: %w", c.ObotID, err) + return fmt.Errorf("failed to copy project %s: %w", c.ProjectID, err) } // If a name was specified, update the project name @@ -113,11 +113,11 @@ func (c *CreateObot) Run(cmd *cobra.Command, _ []string) error { // Create the project project, err = c.root.Client.CreateProject(cmd.Context(), assistantID, manifest) if err != nil { - return fmt.Errorf("failed to create obot: %w", err) + return fmt.Errorf("failed to create project: %w", err) } } // Print the result - fmt.Printf("Created new obot: %s (ID: %s) using base agent: %s\n", project.Name, project.ID, project.AssistantID) + fmt.Printf("Created new project: %s (ID: %s) using base agent: %s\n", project.Name, project.ID, project.AssistantID) return nil } diff --git a/pkg/cli/obots_rm.go b/pkg/cli/projects_rm.go similarity index 70% rename from pkg/cli/obots_rm.go rename to pkg/cli/projects_rm.go index 1d33a91e6a..3945aefa58 100644 --- a/pkg/cli/obots_rm.go +++ b/pkg/cli/projects_rm.go @@ -11,21 +11,21 @@ import ( "github.com/spf13/cobra" ) -// DeleteObot implements the 'obot obot rm' subcommand -type DeleteObot struct { +// DeleteProject implements the 'obot projects rm' subcommand +type DeleteProject struct { root *Obot Force bool `usage:"Skip confirmation prompt" short:"f"` } -func (c *DeleteObot) Customize(cmd *cobra.Command) { +func (c *DeleteProject) Customize(cmd *cobra.Command) { cmd.Use = "rm [ID...]" - cmd.Short = "Delete one or more obots" - cmd.Long = "Delete one or more obots by ID" + cmd.Short = "Delete one or more projects" + cmd.Long = "Delete one or more projects by ID" cmd.Aliases = []string{"remove", "delete"} cmd.Args = cobra.MinimumNArgs(1) } -func (c *DeleteObot) Run(cmd *cobra.Command, args []string) error { +func (c *DeleteProject) Run(cmd *cobra.Command, args []string) error { // Collect valid IDs first and validate them var validIDs []string var validProjects []*types.Project @@ -34,14 +34,14 @@ func (c *DeleteObot) Run(cmd *cobra.Command, args []string) error { for _, id := range args { // Check if ID has the project prefix (both p1- format and p1* format) if !strings.HasPrefix(id, system.ProjectPrefix) { - errs = append(errs, fmt.Errorf("%s is not a valid obot ID (should start with p1)", id)) + errs = append(errs, fmt.Errorf("%s is not a valid project ID (should start with p1)", id)) continue } // Get project details to determine the assistant ID projectInfo, err := c.root.Client.GetProject(cmd.Context(), id) if err != nil { - errs = append(errs, fmt.Errorf("failed to get obot details for %s: %w", id, err)) + errs = append(errs, fmt.Errorf("failed to get project details for %s: %w", id, err)) continue } @@ -55,7 +55,7 @@ func (c *DeleteObot) Run(cmd *cobra.Command, args []string) error { // If not forcing, confirm with user if !c.Force { - fmt.Println("You are about to delete the following obots:") + fmt.Println("You are about to delete the following projects:") for i, project := range validProjects { fmt.Printf(" %s: %s\n", validIDs[i], project.Name) } @@ -76,9 +76,9 @@ func (c *DeleteObot) Run(cmd *cobra.Command, args []string) error { for i, id := range validIDs { project := validProjects[i] if err := c.root.Client.DeleteProject(cmd.Context(), project.AssistantID, id); err != nil { - errs = append(errs, fmt.Errorf("failed to delete obot %s: %w", id, err)) + errs = append(errs, fmt.Errorf("failed to delete project %s: %w", id, err)) } else { - fmt.Printf("Obot deleted: %s (%s)\n", id, project.Name) + fmt.Printf("Project deleted: %s (%s)\n", id, project.Name) } } diff --git a/pkg/cli/rm.go b/pkg/cli/rm.go deleted file mode 100644 index 56da83bcd6..0000000000 --- a/pkg/cli/rm.go +++ /dev/null @@ -1,70 +0,0 @@ -package cli - -import ( - "errors" - "fmt" - - "github.com/obot-platform/obot/pkg/system" - "github.com/spf13/cobra" -) - -type Delete struct { - root *Obot -} - -func (l *Delete) Customize(cmd *cobra.Command) { - cmd.Use = "delete [flags] ID..." - cmd.Aliases = []string{"rm", "del"} -} - -func (l *Delete) Run(cmd *cobra.Command, args []string) error { - var errs []error - for _, id := range args { - if len(id) < 1 { - continue - } - - switch { - case system.IsThreadID(id): - if err := l.root.Client.DeleteThread(cmd.Context(), id); err != nil { - errs = append(errs, err) - } else { - fmt.Printf("Thread deleted: %s\n", id) - } - case system.IsAgentID(id): - if err := l.root.Client.DeleteAgent(cmd.Context(), id); err != nil { - errs = append(errs, err) - } else { - fmt.Printf("Agent deleted: %s\n", id) - } - case system.IsWorkflowID(id): - if err := l.root.Client.DeleteWorkflow(cmd.Context(), id); err != nil { - errs = append(errs, err) - } else { - fmt.Printf("Workflow deleted: %s\n", id) - } - case system.IsRunID(id): - if err := l.root.Client.DeleteRun(cmd.Context(), id); err != nil { - errs = append(errs, err) - } else { - fmt.Printf("Workflow deleted: %s\n", id) - } - case system.IsWebhookID(id): - if err := l.root.Client.DeleteWebhook(cmd.Context(), id); err != nil { - errs = append(errs, err) - } else { - fmt.Printf("Webhook deleted: %s\n", id) - } - case system.IsEmailReceiverID(id): - if err := l.root.Client.DeleteEmailReceiver(cmd.Context(), id); err != nil { - errs = append(errs, err) - } else { - fmt.Printf("Email receiver deleted: %s\n", id) - } - default: - errs = append(errs, errors.New("invalid ID: "+id)) - } - } - - return errors.Join(errs...) -} diff --git a/pkg/cli/root.go b/pkg/cli/root.go index 621e6acdcb..170d77151d 100644 --- a/pkg/cli/root.go +++ b/pkg/cli/root.go @@ -42,25 +42,13 @@ func New() *cobra.Command { }, } return cmd.Command(root, - &Create{root: root}, - &Agents{root: root}, - cmd.Command(&Obots{root: root}, - &CreateObot{root: root}, - &DeleteObot{root: root}), - &Catalog{root: root}, - &Edit{root: root}, - &Update{root: root}, - &Delete{root: root}, - &Invoke{root: root}, + &Server{}, &Tasks{root: root}, cmd.Command(&Threads{root: root}, &ThreadPrint{root: root}), - cmd.Command(&Credentials{root: root}, &CredentialsDelete{root: root}), cmd.Command(&Runs{root: root}, &Debug{root: root}, &RunPrint{root: root}), - cmd.Command(&Tools{root: root}, - &ToolUnregister{root: root}, - &ToolRegister{root: root}, - &ToolUpdate{root: root}), - &Server{}, + cmd.Command(&Projects{root: root}, + &CreateProject{root: root}, + &DeleteProject{root: root}), &Token{root: root}, &Version{}, ) diff --git a/pkg/cli/tools.go b/pkg/cli/tools.go deleted file mode 100644 index 556e0eb2f4..0000000000 --- a/pkg/cli/tools.go +++ /dev/null @@ -1,67 +0,0 @@ -package cli - -import ( - "fmt" - - "github.com/obot-platform/obot/apiclient" - "github.com/obot-platform/obot/apiclient/types" - "github.com/spf13/cobra" -) - -type Tools struct { - root *Obot - Quiet bool `usage:"Only print IDs of tools" short:"q"` - Output string `usage:"Output format (table, json, yaml)" short:"o" default:"table"` -} - -func (l *Tools) Customize(cmd *cobra.Command) { - cmd.Use = "tools [flags]" - cmd.Aliases = []string{"tool", "tl"} -} - -func (l *Tools) Run(cmd *cobra.Command, args []string) error { - var ( - toolRefs types.ToolReferenceList - err error - ) - if len(args) > 0 { - for _, arg := range args { - toolRef, err := l.root.Client.GetToolReference(cmd.Context(), arg) - if err != nil { - return err - } - toolRefs.Items = append(toolRefs.Items, *toolRef) - } - } else { - toolRefs, err = l.root.Client.ListToolReferences(cmd.Context(), apiclient.ListToolReferencesOptions{}) - if err != nil { - return err - } - } - - if ok, err := output(l.Output, toolRefs); ok || err != nil { - return err - } - - if l.Quiet { - for _, toolRef := range toolRefs.Items { - fmt.Println(toolRef.ID) - } - return nil - } - - w := newTable("ID", "NAME", "REF", "DESCRIPTION", "TYPE") - for _, toolRef := range toolRefs.Items { - desc := toolRef.Description - if toolRef.Error != "" { - desc = toolRef.Error - } - ref := toolRef.Reference - if toolRef.Builtin { - ref = "builtin" - } - w.WriteRow(toolRef.ID, toolRef.Name, ref, desc, string(toolRef.ToolType)) - } - - return w.Err() -} diff --git a/pkg/cli/tools_register.go b/pkg/cli/tools_register.go deleted file mode 100644 index 0c8efdc88c..0000000000 --- a/pkg/cli/tools_register.go +++ /dev/null @@ -1,36 +0,0 @@ -package cli - -import ( - "fmt" - - "github.com/obot-platform/obot/apiclient/types" - "github.com/spf13/cobra" -) - -type ToolRegister struct { - root *Obot - Quiet bool `usage:"Only print IDs of created tool references:" short:"q"` -} - -func (l *ToolRegister) Customize(cmd *cobra.Command) { - cmd.Use = "register [flags] NAME REFERENCE" - cmd.Args = cobra.ExactArgs(2) - cmd.Aliases = []string{"add", "create", "new"} -} - -func (l *ToolRegister) Run(cmd *cobra.Command, args []string) error { - tr, err := l.root.Client.CreateToolReference(cmd.Context(), types.ToolReferenceManifest{ - Name: args[0], - ToolType: types.ToolReferenceTypeTool, - Reference: args[1], - }) - if err != nil { - return err - } - if l.Quiet { - fmt.Println(tr.ID) - } else { - fmt.Println("Tool reference created:", tr.ID) - } - return nil -} diff --git a/pkg/cli/tools_unregister.go b/pkg/cli/tools_unregister.go deleted file mode 100644 index 14a236d07f..0000000000 --- a/pkg/cli/tools_unregister.go +++ /dev/null @@ -1,32 +0,0 @@ -package cli - -import ( - "fmt" - - "github.com/obot-platform/obot/apiclient/types" - "github.com/spf13/cobra" -) - -type ToolUnregister struct { - root *Obot - Quiet bool `usage:"Only print IDs of unregistered tool references" short:"q"` -} - -func (l *ToolUnregister) Customize(cmd *cobra.Command) { - cmd.Use = "unregister [flags] [ID...]" - cmd.Aliases = []string{"rm", "del", "d"} -} - -func (l *ToolUnregister) Run(cmd *cobra.Command, args []string) error { - for _, arg := range args { - if err := l.root.Client.DeleteToolReference(cmd.Context(), arg, types.ToolReferenceTypeTool); err != nil { - return err - } - if l.Quiet { - fmt.Println(arg) - } else { - fmt.Println("Tool reference deleted:", arg) - } - } - return nil -} diff --git a/pkg/cli/tools_update.go b/pkg/cli/tools_update.go deleted file mode 100644 index 984b22be78..0000000000 --- a/pkg/cli/tools_update.go +++ /dev/null @@ -1,30 +0,0 @@ -package cli - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -type ToolUpdate struct { - root *Obot - Quiet bool `usage:"Only print IDs of updated step template" short:"q"` -} - -func (l *ToolUpdate) Customize(cmd *cobra.Command) { - cmd.Use = "update [flags] NAME REFERENCE" - cmd.Args = cobra.ExactArgs(2) -} - -func (l *ToolUpdate) Run(cmd *cobra.Command, args []string) error { - tr, err := l.root.Client.UpdateToolReference(cmd.Context(), args[0], args[1]) - if err != nil { - return err - } - if l.Quiet { - fmt.Println(tr.ID) - } else { - fmt.Println("Step template updated:", tr.ID) - } - return nil -} diff --git a/pkg/cli/update.go b/pkg/cli/update.go deleted file mode 100644 index 3240968523..0000000000 --- a/pkg/cli/update.go +++ /dev/null @@ -1,63 +0,0 @@ -package cli - -import ( - "fmt" - "os" - - "github.com/obot-platform/obot/apiclient/types" - "github.com/obot-platform/obot/pkg/system" - "github.com/spf13/cobra" - "sigs.k8s.io/yaml" -) - -type Update struct { - root *Obot - Quiet bool `usage:"Only print IDs of updated agent/workflow" short:"q"` -} - -func (l *Update) Customize(cmd *cobra.Command) { - cmd.Use = "update [flags] [ID] [MANIFEST_FILE]" - cmd.Args = cobra.ExactArgs(2) -} - -func (l *Update) Run(cmd *cobra.Command, args []string) error { - id := args[0] - data, err := os.ReadFile(args[1]) - if err != nil { - return err - } - - if system.IsWorkflowID(id) { - var newManifest types.WorkflowManifest - if err := yaml.Unmarshal(data, &newManifest); err != nil { - return err - } - - wf, err := l.root.Client.UpdateWorkflow(cmd.Context(), id, newManifest) - if err != nil { - return err - } - if l.Quiet { - fmt.Println(wf.ID) - return nil - } - fmt.Printf("Workflow updated: %s\n", wf.ID) - return nil - } - - var newManifest types.AgentManifest - if err := yaml.Unmarshal(data, &newManifest); err != nil { - return err - } - - agent, err := l.root.Client.UpdateAgent(cmd.Context(), id, newManifest) - if err != nil { - return err - } - if l.Quiet { - fmt.Println(agent.ID) - return nil - } - fmt.Printf("Agent updated: %s\n", agent.ID) - return nil -}