From 665698be70e1fd84b2deacc40202b89668912891 Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Tue, 13 May 2025 19:36:32 +0200 Subject: [PATCH 1/3] =?UTF-8?q?[AGENT-133]=20Added=20=E2=80=9Ctest?= =?UTF-8?q?=E2=80=9D=20command?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +++ cmd/agent.go | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9d5366ff..d3f0e665 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,9 @@ agentuity agent list # Delete one or more Agents agentuity agent delete + +# Test an Agent by sending a payload to its webhook +agentuity agent test --agent-id --payload '{"key": "value"}' ``` ### Development and Deployment diff --git a/cmd/agent.go b/cmd/agent.go index 38e53395..0bf31c43 100644 --- a/cmd/agent.go +++ b/cmd/agent.go @@ -699,13 +699,73 @@ Examples: }, } +var agentTestCmd = &cobra.Command{ + Use: "test", + Short: "Test an agent", + Run: func(cmd *cobra.Command, args []string) { + logger := env.NewLogger(cmd) + + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGINT, syscall.SIGTERM) + defer cancel() + theproject := project.EnsureProject(ctx, cmd) + + agentID, _ := cmd.Flags().GetString("agent-id") + payload, _ := cmd.Flags().GetString("payload") + + if agentID == "" { + keys, state := reconcileAgentList(logger, cmd, theproject.APIURL, theproject.Token, theproject) + if len(keys) == 0 { + tui.ShowWarning("no Agents found") + tui.ShowBanner("Create a new Agent", tui.Text("Use the ")+tui.Command("agent new")+tui.Text(" command to create a new Agent"), false) + return + } + var options []tui.Option + for _, v := range keys { + options = append(options, tui.Option{ + ID: state[v].Agent.ID, + Text: tui.PadRight(state[v].Agent.Name, 20, " ") + tui.Muted(state[v].Agent.ID), + }) + } + agentID = tui.Select(logger, "Select an agent", "Select the agent you want to test", options) + agentID = strings.Replace(agentID, "agent_", "", 1) + } + + if payload == "" { + payload = tui.Input(logger, "Enter the payload to send to the agent", "{\"hello\": \"world\"}") + } + + apikey, err := agent.GetApiKey(context.Background(), logger, theproject.APIURL, theproject.Token, agentID) + if err != nil { + errsystem.New(errsystem.ErrApiRequest, err, errsystem.WithContextMessage("Failed to get agent API key")).ShowErrorAndExit() + } + + client := util.NewAPIClient(ctx, logger, theproject.TransportURL, apikey) + var resp agent.Response[any] + if err := client.Do("POST", fmt.Sprintf("/webhook/%s", agentID), strings.NewReader(payload), &resp); err != nil { + logger.Fatal("Failed to send request: %s", err) + } + fmt.Println("Success:", resp.Success) + fmt.Println("Message:", resp.Message) + if sessionID, ok := resp.Data.(map[string]interface{})["sessionId"]; ok { + fmt.Println("Session ID:", sessionID) + } + + }, +} + func init() { rootCmd.AddCommand(agentCmd) agentCmd.AddCommand(agentCreateCmd) agentCmd.AddCommand(agentListCmd) agentCmd.AddCommand(agentDeleteCmd) agentCmd.AddCommand(agentGetApiKeyCmd) - for _, cmd := range []*cobra.Command{agentListCmd, agentCreateCmd, agentDeleteCmd, agentGetApiKeyCmd} { + + agentTestCmd.Flags().String("agent-id", "", "The ID of the agent to test") + agentTestCmd.Flags().String("payload", "", "The payload to send to the agent") + + agentCmd.AddCommand(agentTestCmd) + + for _, cmd := range []*cobra.Command{agentListCmd, agentCreateCmd, agentDeleteCmd, agentGetApiKeyCmd, agentTestCmd} { cmd.Flags().StringP("dir", "d", "", "The project directory") cmd.Flags().String("templates-dir", "", "The directory to load the templates. Defaults to loading them from the github.com/agentuity/templates repository") } @@ -716,4 +776,5 @@ func init() { for _, cmd := range []*cobra.Command{agentCreateCmd, agentDeleteCmd} { cmd.Flags().Bool("force", false, "Force the creation of the agent even if it already exists") } + } From 25bd8fc1f2ac81ae9278ff69519bca7868af3264 Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Wed, 14 May 2025 15:55:30 +0200 Subject: [PATCH 2/3] Use local flag --- cmd/agent.go | 46 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/cmd/agent.go b/cmd/agent.go index 0bf31c43..babb744e 100644 --- a/cmd/agent.go +++ b/cmd/agent.go @@ -4,6 +4,8 @@ import ( "context" "encoding/json" "fmt" + "io" + "net/http" "os" "os/signal" "path/filepath" @@ -13,6 +15,7 @@ import ( "syscall" "github.com/agentuity/cli/internal/agent" + "github.com/agentuity/cli/internal/dev" "github.com/agentuity/cli/internal/errsystem" "github.com/agentuity/cli/internal/project" "github.com/agentuity/cli/internal/templates" @@ -711,6 +714,7 @@ var agentTestCmd = &cobra.Command{ agentID, _ := cmd.Flags().GetString("agent-id") payload, _ := cmd.Flags().GetString("payload") + local, _ := cmd.Flags().GetBool("local") if agentID == "" { keys, state := reconcileAgentList(logger, cmd, theproject.APIURL, theproject.Token, theproject) @@ -738,18 +742,43 @@ var agentTestCmd = &cobra.Command{ if err != nil { errsystem.New(errsystem.ErrApiRequest, err, errsystem.WithContextMessage("Failed to get agent API key")).ShowErrorAndExit() } + endpoint := fmt.Sprintf("%s/webhook/%s", theproject.TransportURL, agentID) + if local { + port, _ := dev.FindAvailablePort(theproject) + endpoint = fmt.Sprintf("http://localhost:%d/agent_%s", port, agentID) + } - client := util.NewAPIClient(ctx, logger, theproject.TransportURL, apikey) - var resp agent.Response[any] - if err := client.Do("POST", fmt.Sprintf("/webhook/%s", agentID), strings.NewReader(payload), &resp); err != nil { - logger.Fatal("Failed to send request: %s", err) + // use http package to send a POST request to the agent + req, err := http.NewRequest("POST", endpoint, strings.NewReader(payload)) + if err != nil { + logger.Fatal("Failed to create request: %s", err) } - fmt.Println("Success:", resp.Success) - fmt.Println("Message:", resp.Message) - if sessionID, ok := resp.Data.(map[string]interface{})["sessionId"]; ok { - fmt.Println("Session ID:", sessionID) + // check if payload is json + if json.Valid([]byte(payload)) { + req.Header.Set("Content-Type", "application/json") + } else { + req.Header.Set("Content-Type", "application/octet-stream") + } + if apikey != "" { + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", apikey)) } + resp, err := http.DefaultClient.Do(req) + if err != nil { + logger.Fatal("Failed to send request: %s", err) + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + logger.Fatal("Failed to read response: %s", err) + } + var jsonBody map[string]interface{} + if json.Unmarshal(body, &jsonBody) == nil { + stringified, _ := json.MarshalIndent(jsonBody, "", " ") + tui.ShowSuccess("Agent Test: %s", tui.Paragraph(tui.Bold(string(stringified)))) + } else { + tui.ShowSuccess("Agent Test: %s", tui.Paragraph(tui.Bold(string(body)))) + } }, } @@ -762,6 +791,7 @@ func init() { agentTestCmd.Flags().String("agent-id", "", "The ID of the agent to test") agentTestCmd.Flags().String("payload", "", "The payload to send to the agent") + agentTestCmd.Flags().Bool("local", false, "Enable local testing") agentCmd.AddCommand(agentTestCmd) From bf91b88b2a57179465400759a68da52d22c28101 Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Wed, 14 May 2025 18:07:16 +0200 Subject: [PATCH 3/3] Finishing touches --- cmd/agent.go | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/cmd/agent.go b/cmd/agent.go index babb744e..492c0d01 100644 --- a/cmd/agent.go +++ b/cmd/agent.go @@ -715,7 +715,8 @@ var agentTestCmd = &cobra.Command{ agentID, _ := cmd.Flags().GetString("agent-id") payload, _ := cmd.Flags().GetString("payload") local, _ := cmd.Flags().GetBool("local") - + contentType, _ := cmd.Flags().GetString("content-type") + route, _ := cmd.Flags().GetString("route") if agentID == "" { keys, state := reconcileAgentList(logger, cmd, theproject.APIURL, theproject.Token, theproject) if len(keys) == 0 { @@ -742,7 +743,7 @@ var agentTestCmd = &cobra.Command{ if err != nil { errsystem.New(errsystem.ErrApiRequest, err, errsystem.WithContextMessage("Failed to get agent API key")).ShowErrorAndExit() } - endpoint := fmt.Sprintf("%s/webhook/%s", theproject.TransportURL, agentID) + endpoint := fmt.Sprintf("%s/%s/%s", theproject.TransportURL, route, agentID) if local { port, _ := dev.FindAvailablePort(theproject) endpoint = fmt.Sprintf("http://localhost:%d/agent_%s", port, agentID) @@ -753,16 +754,19 @@ var agentTestCmd = &cobra.Command{ if err != nil { logger.Fatal("Failed to create request: %s", err) } - // check if payload is json - if json.Valid([]byte(payload)) { - req.Header.Set("Content-Type", "application/json") + if contentType == "" { + // check if payload is json + if json.Valid([]byte(payload)) { + req.Header.Set("Content-Type", "application/json") + } else { + req.Header.Set("Content-Type", "text/plain") + } } else { - req.Header.Set("Content-Type", "application/octet-stream") + req.Header.Set("Content-Type", contentType) } if apikey != "" { req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", apikey)) } - resp, err := http.DefaultClient.Do(req) if err != nil { logger.Fatal("Failed to send request: %s", err) @@ -792,6 +796,8 @@ func init() { agentTestCmd.Flags().String("agent-id", "", "The ID of the agent to test") agentTestCmd.Flags().String("payload", "", "The payload to send to the agent") agentTestCmd.Flags().Bool("local", false, "Enable local testing") + agentTestCmd.Flags().String("content-type", "", "The content type to use for the request, will try to detect if not provided") + agentTestCmd.Flags().String("route", "api", "The route to use for the request when --local is false, can be either 'api' or 'webhook'") agentCmd.AddCommand(agentTestCmd)