From c524087f3928d0a6e5b99cd7d5f0550dc5c0c090 Mon Sep 17 00:00:00 2001 From: Bobby Christopher Date: Thu, 24 Apr 2025 15:06:20 -0400 Subject: [PATCH 01/13] cli changes --- cmd/cloud.go | 2 +- cmd/project.go | 30 ++++++++++++++------ internal/project/project.go | 5 +++- internal/ui/project.go | 55 ++++++++++++++++++++++++++----------- 4 files changed, 66 insertions(+), 26 deletions(-) diff --git a/cmd/cloud.go b/cmd/cloud.go index b9690c0c..0cf2034d 100644 --- a/cmd/cloud.go +++ b/cmd/cloud.go @@ -112,7 +112,7 @@ func ShowNewProjectImport(ctx context.Context, logger logger.Logger, cmd *cobra. errsystem.New(errsystem.ErrSaveProject, err, errsystem.WithContextMessage("Error saving project after import")).ShowErrorAndExit() } - saveEnv(dir, result.APIKey) + saveEnv(dir, result.APIKey, result.AgentsKey) }) tui.ShowSuccess("Project imported successfully") } diff --git a/cmd/project.go b/cmd/project.go index 2f6c3627..97aa0d5d 100644 --- a/cmd/project.go +++ b/cmd/project.go @@ -36,22 +36,33 @@ Use the subcommands to manage your projects.`, }, } -func saveEnv(dir string, apikey string) { +func saveEnv(dir string, apikey string, agentsKey string) { filename := filepath.Join(dir, ".env") envLines, err := env.ParseEnvFile(filename) if err != nil { errsystem.New(errsystem.ErrReadConfigurationFile, err, errsystem.WithContextMessage("Failed to parse .env file")).ShowErrorAndExit() } - var found bool + var found map[string]bool = map[string]bool{ + "AGENTUITY_API_KEY": false, + "AGENTUITY_AGENTS_KEY": false, + } + for i, envLine := range envLines { if envLine.Key == "AGENTUITY_API_KEY" { envLines[i].Val = apikey - found = true + found["AGENTUITY_API_KEY"] = true + } + if envLine.Key == "AGENTUITY_AGENTS_KEY" { + envLines[i].Val = apikey + found["AGENTUITY_AGENTS_KEY"] = true } } - if !found { + if !found["AGENTUITY_API_KEY"] { envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_API_KEY", Val: apikey}) } + if !found["AGENTUITY_AGENTS_KEY"] { + envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_AGENTS_KEY", Val: apikey}) + } if err := env.WriteEnvFile(filename, envLines); err != nil { errsystem.New(errsystem.ErrWriteConfigurationFile, err, errsystem.WithContextMessage("Failed to write .env file")).ShowErrorAndExit() } @@ -65,6 +76,7 @@ type InitProjectArgs struct { Name string Description string EnableWebhookAuth bool + AuthType string Provider *templates.TemplateRules Agents []project.AgentConfig } @@ -78,6 +90,7 @@ func initProject(ctx context.Context, logger logger.Logger, args InitProjectArgs Name: args.Name, Description: args.Description, EnableWebhookAuth: args.EnableWebhookAuth, + AuthType: args.AuthType, Dir: args.Dir, Provider: args.Provider.Identifier, Agents: args.Agents, @@ -126,7 +139,7 @@ func initProject(ctx context.Context, logger logger.Logger, args InitProjectArgs errsystem.New(errsystem.ErrSaveProject, err, errsystem.WithContextMessage("Failed to save project to disk")).ShowErrorAndExit() } - saveEnv(args.Dir, result.APIKey) + saveEnv(args.Dir, result.APIKey, result.AgentsKey) return result } @@ -540,7 +553,8 @@ Examples: Description: description, Provider: rules, Agents: agents, - EnableWebhookAuth: authType != "none", + EnableWebhookAuth: authType == "project" || authType == "agent", + AuthType: authType, }) // remember our choices @@ -562,7 +576,7 @@ Examples: para = append(para, tui.Secondary("1. Switch into the project directory at ")+tui.Directory(projectDir)) para = append(para, tui.Secondary("2. Run ")+tui.Command("dev")+tui.Secondary(" to run the project locally in development mode")) para = append(para, tui.Secondary("3. Run ")+tui.Command("deploy")+tui.Secondary(" to deploy the project to the Agentuity Agent Cloud")) - if authType != "none" { + if authType == "project" || authType == "agent" { para = append(para, tui.Secondary("4. Run ")+tui.Command("agent apikey")+tui.Secondary(" to fetch the Webhook API key for the agent")) } para = append(para, tui.Secondary("🏠 Access your project at ")+tui.Link("%s/projects/%s", appUrl, projectData.ProjectId)) @@ -811,6 +825,6 @@ func init() { projectNewCmd.Flags().StringP("template", "t", "", "The template to use for the project") projectNewCmd.Flags().Bool("force", false, "Force the project to be created even if the directory already exists") projectNewCmd.Flags().String("templates-dir", "", "The directory to load the templates. Defaults to loading them from the github.com/agentuity/templates repository") - projectNewCmd.Flags().String("auth", "bearer", "The authentication type for the agent (bearer or none)") + projectNewCmd.Flags().String("auth", "project", "The authentication type for the agent (project, agent, or none)") projectNewCmd.Flags().String("action", "github-app", "The action to take for the project (github-action, github-app, none)") } diff --git a/internal/project/project.go b/internal/project/project.go index 6fd46d72..0c9019b2 100644 --- a/internal/project/project.go +++ b/internal/project/project.go @@ -42,6 +42,7 @@ type initProjectResult struct { type ProjectData struct { APIKey string `json:"api_key"` + AgentsKey string `json:"agentsKey"` ProjectId string `json:"id"` OrgId string `json:"orgId"` Env map[string]string `json:"env"` @@ -60,6 +61,7 @@ type InitProjectArgs struct { Description string EnableWebhookAuth bool Agents []AgentConfig + AuthType string } // InitProject will create a new project in the organization. @@ -80,6 +82,7 @@ func InitProject(ctx context.Context, logger logger.Logger, args InitProjectArgs "description": args.Description, "enableWebhookAuth": args.EnableWebhookAuth, "agents": agents, + "authType": args.AuthType, } logger.Trace("sending new project payload: %s", cstr.JSONStringify(payload)) @@ -89,7 +92,6 @@ func InitProject(ctx context.Context, logger logger.Logger, args InitProjectArgs if err := client.Do("POST", initPath, payload, &result); err != nil { return nil, err } - return &result.Data, nil } @@ -375,6 +377,7 @@ type ProjectImportResponse struct { ID string `json:"id"` Agents []AgentConfig `json:"agents"` APIKey string `json:"apiKey"` + AgentsKey string `json:"agentsKey"` IOAuthToken string `json:"ioAuthToken"` } diff --git a/internal/ui/project.go b/internal/ui/project.go index e3507a90..7567b68e 100644 --- a/internal/ui/project.go +++ b/internal/ui/project.go @@ -305,8 +305,12 @@ func initialProjectModel(initialForm ProjectForm) projectFormModel { } if initialForm.AgentAuthType != "" { agentAuthType = initialForm.AgentAuthType - if agentAuthType == "apikey" { + if agentAuthType == "none" { + authCursor = 0 + } else if agentAuthType == "project" { authCursor = 1 + } else if agentAuthType == "agent" { + authCursor = 2 } } @@ -583,10 +587,15 @@ func (m projectFormModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case "left", "esc": if m.step == 3 && !m.agentName.Focused() && !m.agentDesc.Focused() { - if m.authCursor == 1 { - // When on auth options and API Key is selected, focus None - m.authCursor = 0 - m.agentAuthType = "none" + if m.authCursor > 0 { + m.authCursor-- + if m.authCursor == 0 { + m.agentAuthType = "none" + } else if m.authCursor == 1 { + m.agentAuthType = "project" + } else if m.authCursor == 2 { + m.agentAuthType = "agent" + } break } } @@ -635,9 +644,17 @@ func (m projectFormModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case "right": if m.step == 3 && !m.agentName.Focused() && !m.agentDesc.Focused() { - // Toggle between None and API Key - m.authCursor = 1 - m.agentAuthType = "apikey" + // Toggle between None, Project API Key, and Agent API Key + if m.authCursor < 2 { + m.authCursor++ + if m.authCursor == 0 { + m.agentAuthType = "none" + } else if m.authCursor == 1 { + m.agentAuthType = "project" + } else if m.authCursor == 2 { + m.agentAuthType = "agent" + } + } } else { // Only advance if current step is valid if m.step == 0 && m.cursor < len(m.choices) { @@ -829,8 +846,10 @@ func (m projectFormModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { // When on auth options, confirm selection and move to deployment step if m.authCursor == 0 { m.agentAuthType = "none" - } else { - m.agentAuthType = "apikey" + } else if m.authCursor == 1 { + m.agentAuthType = "project" + } else if m.authCursor == 2 { + m.agentAuthType = "agent" } m.step++ m.cursor = m.stepCursors[m.step] @@ -1260,15 +1279,19 @@ func (m projectFormModel) View() string { content.WriteString(selectedItemStyle.Render("Authentication") + "\n") if !m.agentName.Focused() && !m.agentDesc.Focused() { if m.authCursor == 0 { - content.WriteString(selectedItemStyle.UnsetForeground().Render("> [•] None") + " " + itemStyle.UnsetForeground().Render(" [ ] API Key") + "\n") - } else { - content.WriteString(itemStyle.UnsetForeground().Render(" [ ] None") + " " + selectedItemStyle.UnsetForeground().Render("> [•] API Key") + "\n") + content.WriteString(itemStyle.UnsetForeground().Render(" [•] None [ ] Project API Key [ ] Agent API Key\n")) + } else if m.authCursor == 1 { + content.WriteString(itemStyle.UnsetForeground().Render(" [ ] None [•] Project API Key [ ] Agent API Key\n")) + } else if m.authCursor == 2 { + content.WriteString(itemStyle.UnsetForeground().Render(" [ ] None [ ] Project API Key [•] Agent API Key\n")) } } else { if m.authCursor == 0 { - content.WriteString(itemStyle.UnsetForeground().Render(" [•] None [ ] API Key\n")) - } else { - content.WriteString(itemStyle.UnsetForeground().Render(" [ ] None [•] API Key\n")) + content.WriteString(itemStyle.UnsetForeground().Render(" [•] None [ ] Project API Key [ ] Agent API Key\n")) + } else if m.authCursor == 1 { + content.WriteString(itemStyle.UnsetForeground().Render(" [ ] None [•] Project API Key [ ] Agent API Key\n")) + } else if m.authCursor == 2 { + content.WriteString(itemStyle.UnsetForeground().Render(" [ ] None [ ] Project API Key [•] Agent API Key\n")) } } From 0b5d38a44d014fcfaf93ab27059239d361b4af79 Mon Sep 17 00:00:00 2001 From: Bobby Christopher Date: Mon, 12 May 2025 12:29:34 -0400 Subject: [PATCH 02/13] added changes to support project auth token --- cmd/agent.go | 5 +++-- cmd/cloud.go | 2 +- cmd/project.go | 24 ++++++++++++------------ internal/project/project.go | 4 ++-- internal/ui/project.go | 2 +- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/cmd/agent.go b/cmd/agent.go index 38e53395..11a61185 100644 --- a/cmd/agent.go +++ b/cmd/agent.go @@ -171,8 +171,9 @@ func getAgentAuthType(logger logger.Logger, authType string) string { } } auth := tui.Select(logger, "Select your Agent's webhook authentication method", "Do you want to secure the webhook or make it publicly available?", []tui.Option{ - {Text: tui.PadRight("API Key", 10, " ") + tui.Muted("Bearer Token (will be generated for you)"), ID: "bearer"}, - {Text: tui.PadRight("None", 10, " ") + tui.Muted("No Authentication Required"), ID: "none"}, + {Text: tui.PadRight("API Key", 20, " ") + tui.Muted("Bearer Token (will be generated for you)"), ID: "bearer"}, + {Text: tui.PadRight("Project API Key", 20, " ") + tui.Muted("The Project Key attched to your project"), ID: "project"}, + {Text: tui.PadRight("None", 20, " ") + tui.Muted("No Authentication Required"), ID: "none"}, }) return auth } diff --git a/cmd/cloud.go b/cmd/cloud.go index 1c985d08..b142de93 100644 --- a/cmd/cloud.go +++ b/cmd/cloud.go @@ -113,7 +113,7 @@ func ShowNewProjectImport(ctx context.Context, logger logger.Logger, cmd *cobra. errsystem.New(errsystem.ErrSaveProject, err, errsystem.WithContextMessage("Error saving project after import")).ShowErrorAndExit() } - saveEnv(dir, result.APIKey, result.AgentsKey) + saveEnv(dir, result.APIKey, result.ProjectKey) }) tui.ShowSuccess("Project imported successfully") } diff --git a/cmd/project.go b/cmd/project.go index 8011efda..c0d0c8f0 100644 --- a/cmd/project.go +++ b/cmd/project.go @@ -36,15 +36,15 @@ Use the subcommands to manage your projects.`, }, } -func saveEnv(dir string, apikey string, agentsKey string) { +func saveEnv(dir string, apikey string, projectKey string) { filename := filepath.Join(dir, ".env") envLines, err := env.ParseEnvFile(filename) if err != nil { errsystem.New(errsystem.ErrReadConfigurationFile, err, errsystem.WithContextMessage("Failed to parse .env file")).ShowErrorAndExit() } var found map[string]bool = map[string]bool{ - "AGENTUITY_API_KEY": false, - "AGENTUITY_AGENTS_KEY": false, + "AGENTUITY_API_KEY": false, + "AGENTUITY_PROJECT_KEY": false, } for i, envLine := range envLines { @@ -52,16 +52,16 @@ func saveEnv(dir string, apikey string, agentsKey string) { envLines[i].Val = apikey found["AGENTUITY_API_KEY"] = true } - if envLine.Key == "AGENTUITY_AGENTS_KEY" { - envLines[i].Val = apikey - found["AGENTUITY_AGENTS_KEY"] = true + if envLine.Key == "AGENTUITY_PROJECT_KEY" { + envLines[i].Val = projectKey + found["AGENTUITY_PROJECT_KEY"] = true } } if !found["AGENTUITY_API_KEY"] { envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_API_KEY", Val: apikey}) } - if !found["AGENTUITY_AGENTS_KEY"] { - envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_AGENTS_KEY", Val: apikey}) + if !found["AGENTUITY_PROJECT_KEY"] { + envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_PROJECT_KEY", Val: projectKey}) } if err := env.WriteEnvFile(filename, envLines); err != nil { errsystem.New(errsystem.ErrWriteConfigurationFile, err, errsystem.WithContextMessage("Failed to write .env file")).ShowErrorAndExit() @@ -139,7 +139,7 @@ func initProject(ctx context.Context, logger logger.Logger, args InitProjectArgs errsystem.New(errsystem.ErrSaveProject, err, errsystem.WithContextMessage("Failed to save project to disk")).ShowErrorAndExit() } - saveEnv(args.Dir, result.APIKey, result.AgentsKey) + saveEnv(args.Dir, result.APIKey, result.ProjectKey) return result } @@ -553,7 +553,7 @@ Examples: Description: description, Provider: rules, Agents: agents, - EnableWebhookAuth: authType == "project" || authType == "agent", + EnableWebhookAuth: authType == "project" || authType == "webhook", AuthType: authType, }) @@ -576,7 +576,7 @@ Examples: para = append(para, tui.Secondary("1. Switch into the project directory at ")+tui.Directory(projectDir)) para = append(para, tui.Secondary("2. Run ")+tui.Command("dev")+tui.Secondary(" to run the project locally in development mode")) para = append(para, tui.Secondary("3. Run ")+tui.Command("deploy")+tui.Secondary(" to deploy the project to the Agentuity Agent Cloud")) - if authType == "project" || authType == "agent" { + if authType == "project" || authType == "webhook" { para = append(para, tui.Secondary("4. Run ")+tui.Command("agent apikey")+tui.Secondary(" to fetch the Webhook API key for the agent")) } para = append(para, tui.Secondary("🏠 Access your project at ")+tui.Link("%s/projects/%s", appUrl, projectData.ProjectId)) @@ -825,6 +825,6 @@ func init() { projectNewCmd.Flags().StringP("template", "t", "", "The template to use for the project") projectNewCmd.Flags().Bool("force", false, "Force the project to be created even if the directory already exists") projectNewCmd.Flags().String("templates-dir", "", "The directory to load the templates. Defaults to loading them from the github.com/agentuity/templates repository") - projectNewCmd.Flags().String("auth", "project", "The authentication type for the agent (project, agent, or none)") + projectNewCmd.Flags().String("auth", "project", "The authentication type for the agent (project, webhook, or none)") projectNewCmd.Flags().String("action", "github-app", "The action to take for the project (github-action, github-app, none)") } diff --git a/internal/project/project.go b/internal/project/project.go index 9a3cf011..ada36b7b 100644 --- a/internal/project/project.go +++ b/internal/project/project.go @@ -43,7 +43,7 @@ type initProjectResult struct { type ProjectData struct { APIKey string `json:"api_key"` - AgentsKey string `json:"agentsKey"` + ProjectKey string `json:"projectKey"` ProjectId string `json:"id"` OrgId string `json:"orgId"` Env map[string]string `json:"env"` @@ -378,7 +378,7 @@ type ProjectImportResponse struct { ID string `json:"id"` Agents []AgentConfig `json:"agents"` APIKey string `json:"apiKey"` - AgentsKey string `json:"agentsKey"` + ProjectKey string `json:"projectKey"` IOAuthToken string `json:"ioAuthToken"` } diff --git a/internal/ui/project.go b/internal/ui/project.go index 7567b68e..e8d2f42c 100644 --- a/internal/ui/project.go +++ b/internal/ui/project.go @@ -309,7 +309,7 @@ func initialProjectModel(initialForm ProjectForm) projectFormModel { authCursor = 0 } else if agentAuthType == "project" { authCursor = 1 - } else if agentAuthType == "agent" { + } else if agentAuthType == "bearer" { authCursor = 2 } } From 5e18caaf6d6503c2cb2c8ab55f77f27fae187dd8 Mon Sep 17 00:00:00 2001 From: Bobby Christopher Date: Mon, 12 May 2025 13:40:33 -0400 Subject: [PATCH 03/13] alomst there --- cmd/agent.go | 2 +- internal/project/project.go | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cmd/agent.go b/cmd/agent.go index 11a61185..44c5f0b1 100644 --- a/cmd/agent.go +++ b/cmd/agent.go @@ -165,7 +165,7 @@ var agentDeleteCmd = &cobra.Command{ func getAgentAuthType(logger logger.Logger, authType string) string { if authType != "" { switch authType { - case "bearer", "none": + case "project", "bearer", "none": return authType default: } diff --git a/internal/project/project.go b/internal/project/project.go index ada36b7b..2d285777 100644 --- a/internal/project/project.go +++ b/internal/project/project.go @@ -77,9 +77,10 @@ func InitProject(ctx context.Context, logger logger.Logger, args InitProjectArgs }) } payload := map[string]any{ - "organization_id": args.OrgId, - "provider": args.Provider, - "name": args.Name, + "organization_id": args.OrgId, + "provider": args.Provider, + "name": args.Name, + "description": args.Description, "enableWebhookAuth": args.EnableWebhookAuth, "agents": agents, From ece25b0c06aa6a258fb53d4d4587a2c02c327ba9 Mon Sep 17 00:00:00 2001 From: Bobby Christopher Date: Mon, 12 May 2025 13:57:57 -0400 Subject: [PATCH 04/13] I think this is backward compatable --- cmd/project.go | 11 ++++++++++- internal/bundler/openai.go | 2 +- internal/bundler/patch.go | 4 ++-- internal/bundler/vercel_ai.go | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/cmd/project.go b/cmd/project.go index c0d0c8f0..dc8032e9 100644 --- a/cmd/project.go +++ b/cmd/project.go @@ -43,6 +43,7 @@ func saveEnv(dir string, apikey string, projectKey string) { errsystem.New(errsystem.ErrReadConfigurationFile, err, errsystem.WithContextMessage("Failed to parse .env file")).ShowErrorAndExit() } var found map[string]bool = map[string]bool{ + "AGENTUITY_SDK_KEY": false, "AGENTUITY_API_KEY": false, "AGENTUITY_PROJECT_KEY": false, } @@ -52,13 +53,21 @@ func saveEnv(dir string, apikey string, projectKey string) { envLines[i].Val = apikey found["AGENTUITY_API_KEY"] = true } + if envLine.Key == "AGENTUITY_SDK_KEY" { + envLines[i].Val = apikey + found["AGENTUITY_SDK_KEY"] = true + } if envLine.Key == "AGENTUITY_PROJECT_KEY" { envLines[i].Val = projectKey found["AGENTUITY_PROJECT_KEY"] = true } } + + if !found["AGENTUITY_SDK_KEY"] { + envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_SDK_KEY", Val: apikey}) + } if !found["AGENTUITY_API_KEY"] { - envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_API_KEY", Val: apikey}) + envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_SDK_KEY", Val: apikey}) } if !found["AGENTUITY_PROJECT_KEY"] { envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_PROJECT_KEY", Val: projectKey}) diff --git a/internal/bundler/openai.go b/internal/bundler/openai.go index c3064089..3c6ac7a1 100644 --- a/internal/bundler/openai.go +++ b/internal/bundler/openai.go @@ -5,7 +5,7 @@ func init() { Module: "openai", Filename: "index", Body: &patchAction{ - Before: generateEnvGuard("OPENAI_API_KEY", generateGatewayEnvGuard("OPENAI_API_KEY", "process.env.AGENTUITY_API_KEY", "OPENAI_BASE_URL", "openai")), + Before: generateEnvGuard("OPENAI_API_KEY", generateGatewayEnvGuard("OPENAI_API_KEY", "process.env.AGENTUITY_API_KEY || process.env.AGENTUITY_SDK_KEY", "OPENAI_BASE_URL", "openai")), }, } } diff --git a/internal/bundler/patch.go b/internal/bundler/patch.go index 3422210c..eecc5542 100644 --- a/internal/bundler/patch.go +++ b/internal/bundler/patch.go @@ -37,14 +37,14 @@ _args = _newargs;`, index, inject) } func generateEnvGuard(name string, inject string) string { - return fmt.Sprintf(`if (!process.env.%[1]s || process.env.%[1]s === process.env.AGENTUITY_API_KEY) { + return fmt.Sprintf(`if (!process.env.%[1]s || process.env.%[1]s === (process.env.AGENTUITY_API_KEY || process.env.AGENTUITY_SDK_KEY)) { %[2]s }`, name, inject) } func generateGatewayEnvGuard(apikey string, apikeyval string, apibase string, provider string) string { return fmt.Sprintf(`{ - const apikey = process.env.AGENTUITY_API_KEY; + const apikey = process.env.AGENTUITY_API_KEY || process.env.AGENTUITY_SDK_KEY; const url = process.env.AGENTUITY_TRANSPORT_URL; if (url && apikey) { process.env.%[1]s = %[2]s; diff --git a/internal/bundler/vercel_ai.go b/internal/bundler/vercel_ai.go index 66c3cacb..0c34b9cc 100644 --- a/internal/bundler/vercel_ai.go +++ b/internal/bundler/vercel_ai.go @@ -5,7 +5,7 @@ import "fmt" func generateVercelAIProvider(name string, envkey string) string { return generateJSArgsPatch(0, "") + fmt.Sprintf(`const opts = {...(_args[0] ?? {}) }; if (!opts.baseURL) { - const apikey = process.env.AGENTUITY_API_KEY; + const apikey = process.env.AGENTUITY_API_KEY || process.env.AGENTUITY_SDK_KEY; const url = process.env.AGENTUITY_TRANSPORT_URL; if (url && apikey) { opts.apiKey = apikey; From ed2b2cbce7fb09bb6b66e617af342d72f287290a Mon Sep 17 00:00:00 2001 From: Bobby Christopher Date: Mon, 12 May 2025 13:59:12 -0400 Subject: [PATCH 05/13] added one more check --- internal/bundler/anthropic.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/bundler/anthropic.go b/internal/bundler/anthropic.go index a3d08a0f..904f6206 100644 --- a/internal/bundler/anthropic.go +++ b/internal/bundler/anthropic.go @@ -5,7 +5,7 @@ func init() { Module: "@anthropic-ai", Filename: "sdk\\/index.*", Body: &patchAction{ - Before: generateEnvGuard("ANTHROPIC_API_KEY", generateGatewayEnvGuard("ANTHROPIC_API_KEY", "process.env.AGENTUITY_API_KEY", "ANTHROPIC_BASE_URL", "anthropic")), + Before: generateEnvGuard("ANTHROPIC_API_KEY", generateGatewayEnvGuard("ANTHROPIC_API_KEY", "process.env.AGENTUITY_API_KEY || process.env.AGENTUITY_SDK_KEY", "ANTHROPIC_BASE_URL", "anthropic")), }, } } From 1f75ce97e3a583c55227834c636eab265336f3c7 Mon Sep 17 00:00:00 2001 From: Bobby Christopher Date: Tue, 13 May 2025 09:25:11 -0400 Subject: [PATCH 06/13] better dx --- cmd/cloud.go | 10 ++- cmd/project.go | 33 +++++++-- internal/bundler/upgrade.go | 137 ++++++++++++++++++++++-------------- 3 files changed, 120 insertions(+), 60 deletions(-) diff --git a/cmd/cloud.go b/cmd/cloud.go index b142de93..42dfe690 100644 --- a/cmd/cloud.go +++ b/cmd/cloud.go @@ -15,6 +15,7 @@ import ( "time" "github.com/agentuity/cli/internal/agent" + "github.com/agentuity/cli/internal/bundler" "github.com/agentuity/cli/internal/deployer" "github.com/agentuity/cli/internal/errsystem" "github.com/agentuity/cli/internal/ignore" @@ -113,7 +114,14 @@ func ShowNewProjectImport(ctx context.Context, logger logger.Logger, cmd *cobra. errsystem.New(errsystem.ErrSaveProject, err, errsystem.WithContextMessage("Error saving project after import")).ShowErrorAndExit() } - saveEnv(dir, result.APIKey, result.ProjectKey) + saveEnv(bundler.BundleContext{ + Context: ctx, + Logger: logger, + ProjectDir: dir, + Production: true, // TODO: need to come back and look at this + Install: false, + CI: false, + }, dir, result.APIKey, result.ProjectKey, project.Bundler.Language) }) tui.ShowSuccess("Project imported successfully") } diff --git a/cmd/project.go b/cmd/project.go index dc8032e9..aab2bc96 100644 --- a/cmd/project.go +++ b/cmd/project.go @@ -11,6 +11,8 @@ import ( "sort" "syscall" + "github.com/Masterminds/semver" + "github.com/agentuity/cli/internal/bundler" "github.com/agentuity/cli/internal/errsystem" "github.com/agentuity/cli/internal/mcp" "github.com/agentuity/cli/internal/organization" @@ -36,9 +38,11 @@ Use the subcommands to manage your projects.`, }, } -func saveEnv(dir string, apikey string, projectKey string) { +func saveEnv(bcxt bundler.BundleContext, dir string, apikey string, projectKey string, language string) { filename := filepath.Join(dir, ".env") envLines, err := env.ParseEnvFile(filename) + version, err := bundler.GetSDKVersion(language, bcxt) + if err != nil { errsystem.New(errsystem.ErrReadConfigurationFile, err, errsystem.WithContextMessage("Failed to parse .env file")).ShowErrorAndExit() } @@ -63,12 +67,24 @@ func saveEnv(dir string, apikey string, projectKey string) { } } - if !found["AGENTUITY_SDK_KEY"] { - envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_SDK_KEY", Val: apikey}) + gtVersion := version.GreaterThan(semver.MustParse("0.0.114")) + if gtVersion && found["AGENTUITY_API_KEY"] { + // Remove AGENTUITY_API_KEY since it's deprecated in newer SDK versions + for i := len(envLines) - 1; i >= 0; i-- { + if envLines[i].Key == "AGENTUITY_API_KEY" { + envLines = append(envLines[:i], envLines[i+1:]...) + } + } + found["AGENTUITY_API_KEY"] = false } - if !found["AGENTUITY_API_KEY"] { + if !found["AGENTUITY_API_KEY"] && !gtVersion { + envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_API_KEY", Val: apikey}) + } + + if !found["AGENTUITY_SDK_KEY"] { envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_SDK_KEY", Val: apikey}) } + if !found["AGENTUITY_PROJECT_KEY"] { envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_PROJECT_KEY", Val: projectKey}) } @@ -148,7 +164,14 @@ func initProject(ctx context.Context, logger logger.Logger, args InitProjectArgs errsystem.New(errsystem.ErrSaveProject, err, errsystem.WithContextMessage("Failed to save project to disk")).ShowErrorAndExit() } - saveEnv(args.Dir, result.APIKey, result.ProjectKey) + saveEnv(bundler.BundleContext{ + Context: ctx, + Logger: logger, + ProjectDir: args.Dir, + Production: true, // TODO: need to come back and look at this + Install: false, + CI: false, + }, args.Dir, result.APIKey, result.ProjectKey, proj.Bundler.Language) return result } diff --git a/internal/bundler/upgrade.go b/internal/bundler/upgrade.go index 1e7fb9e0..2739382c 100644 --- a/internal/bundler/upgrade.go +++ b/internal/bundler/upgrade.go @@ -53,72 +53,101 @@ type UVLockfile struct { Packages []UVPackage `toml:"package"` } +func getSDKVersionJavascript(ctx BundleContext) (*semver.Version, error) { + var pkg packageJSON + pkgjson := filepath.Join(ctx.ProjectDir, "node_modules", "@agentuity", "sdk", "package.json") + if !util.Exists(pkgjson) { + return nil, fmt.Errorf("package.json not found: %s", pkgjson) + } + content, err := os.ReadFile(pkgjson) + if err != nil { + return nil, err + } + if err := json.Unmarshal(content, &pkg); err != nil { + return nil, err + } + currentVersion := semver.MustParse(pkg.Version) + return currentVersion, nil +} + +func getSDKVersionPython(ctx BundleContext) (*semver.Version, error) { + uvlock := filepath.Join(ctx.ProjectDir, "uv.lock") + if !util.Exists(uvlock) { + return nil, fmt.Errorf("uv.lock not found: %s", uvlock) + } + file, err := os.Open(uvlock) + if err != nil { + return nil, err + } + defer file.Close() + var lockfile UVLockfile + if err := toml.NewDecoder(file).Decode(&lockfile); err != nil { + return nil, err + } + for _, pkg := range lockfile.Packages { + if pkg.Name == "agentuity" { + currentVersion := semver.MustParse(pkg.Version) + return currentVersion, nil + } + } + return nil, fmt.Errorf("agentuity package not found in uv.lock") +} + +func GetSDKVersion(language string, ctx BundleContext) (*semver.Version, error) { + switch language { + case "python": + return getSDKVersionPython(ctx) + case "javascript": + return getSDKVersionJavascript(ctx) + default: + return nil, fmt.Errorf("unsupported language: %s", language) + } +} + func checkForBreakingChanges(ctx BundleContext, language string, runtime string) error { ctx.Logger.Trace("Checking for breaking changes in %s, runtime: %s", language, runtime) switch language { case "python": - uvlock := filepath.Join(ctx.ProjectDir, "uv.lock") - ctx.Logger.Trace("Checking for breaking changes in %s, exists: %t", uvlock, util.Exists(uvlock)) - if util.Exists(uvlock) { - var lockfile UVLockfile - content, err := os.Open(uvlock) - if err != nil { - return err + currentVersion, err := getSDKVersionPython(ctx) + if err != nil { + return err + } + for _, change := range breakingChanges { + if change.Runtime != runtime { + continue } - if err := toml.NewDecoder(content).Decode(&lockfile); err != nil { - return err + c, err := semver.NewConstraint(change.Version) + if err != nil { + return fmt.Errorf("error parsing semver constraint %s: %w", change.Version, err) } - for _, pkg := range lockfile.Packages { - ctx.Logger.Trace("Checking for breaking changes in %s", pkg.Name) - if pkg.Name == "agentuity" { - currentVersion := semver.MustParse(pkg.Version) - for _, change := range breakingChanges { - if change.Runtime != runtime { - continue - } - c, err := semver.NewConstraint(change.Version) - if err != nil { - return fmt.Errorf("error parsing semver constraint %s: %w", change.Version, err) - } - if c.Check(currentVersion) { - if tui.HasTTY { - tui.ShowBanner(change.Title, change.Message, true) - os.Exit(1) - } else { - ctx.Logger.Fatal(change.Message) - } - } - } + if c.Check(currentVersion) { + if tui.HasTTY { + tui.ShowBanner(change.Title, change.Message, true) + os.Exit(1) + } else { + ctx.Logger.Fatal(change.Message) } } } case "javascript": - pkgjson := filepath.Join(ctx.ProjectDir, "node_modules", "@agentuity", "sdk", "package.json") - if util.Exists(pkgjson) { - var pkg packageJSON - content, err := os.ReadFile(pkgjson) - if err != nil { - return err + currentVersion, err := getSDKVersionJavascript(ctx) + if err != nil { + return err + } + for _, change := range breakingChanges { + if change.Runtime != runtime { + continue } - if err := json.Unmarshal(content, &pkg); err != nil { - return err + c, err := semver.NewConstraint(change.Version) + if err != nil { + return fmt.Errorf("error parsing semver constraint %s: %w", change.Version, err) } - currentVersion := semver.MustParse(pkg.Version) - for _, change := range breakingChanges { - if change.Runtime != runtime { - continue - } - c, err := semver.NewConstraint(change.Version) - if err != nil { - return fmt.Errorf("error parsing semver constraint %s: %w", change.Version, err) - } - if c.Check(currentVersion) { - if tui.HasTTY { - tui.ShowBanner(change.Title, change.Message, true) - os.Exit(1) - } else { - ctx.Logger.Fatal(change.Message) - } + if c.Check(currentVersion) { + if tui.HasTTY { + tui.ShowBanner(change.Title, change.Message, true) + os.Exit(1) + } else { + ctx.Logger.Fatal(change.Message) } } } From ed61e0c4ccfcce837c0c43b7e31f3ddb1a372d7f Mon Sep 17 00:00:00 2001 From: Bobby Christopher Date: Tue, 13 May 2025 09:57:38 -0400 Subject: [PATCH 07/13] add version map --- cmd/project.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cmd/project.go b/cmd/project.go index aab2bc96..ad5bf095 100644 --- a/cmd/project.go +++ b/cmd/project.go @@ -43,6 +43,11 @@ func saveEnv(bcxt bundler.BundleContext, dir string, apikey string, projectKey s envLines, err := env.ParseEnvFile(filename) version, err := bundler.GetSDKVersion(language, bcxt) + versions := map[string]string{ + "python": "0.0.83", + "javascript": "0.0.114", + } + if err != nil { errsystem.New(errsystem.ErrReadConfigurationFile, err, errsystem.WithContextMessage("Failed to parse .env file")).ShowErrorAndExit() } @@ -67,7 +72,7 @@ func saveEnv(bcxt bundler.BundleContext, dir string, apikey string, projectKey s } } - gtVersion := version.GreaterThan(semver.MustParse("0.0.114")) + gtVersion := version.GreaterThan(semver.MustParse(versions[language])) if gtVersion && found["AGENTUITY_API_KEY"] { // Remove AGENTUITY_API_KEY since it's deprecated in newer SDK versions for i := len(envLines) - 1; i >= 0; i-- { @@ -85,9 +90,6 @@ func saveEnv(bcxt bundler.BundleContext, dir string, apikey string, projectKey s envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_SDK_KEY", Val: apikey}) } - if !found["AGENTUITY_PROJECT_KEY"] { - envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_PROJECT_KEY", Val: projectKey}) - } if err := env.WriteEnvFile(filename, envLines); err != nil { errsystem.New(errsystem.ErrWriteConfigurationFile, err, errsystem.WithContextMessage("Failed to write .env file")).ShowErrorAndExit() } From 6fb447a94c955bfb251d5c568d40b3bce49bd453 Mon Sep 17 00:00:00 2001 From: Bobby Christopher Date: Tue, 13 May 2025 12:42:54 -0400 Subject: [PATCH 08/13] going I different route --- cmd/cloud.go | 10 +-- cmd/project.go | 29 ++---- internal/bundler/anthropic.go | 2 +- internal/bundler/openai.go | 2 +- internal/bundler/patch.go | 4 +- internal/bundler/upgrade.go | 164 +++++++++++++++++++++++++--------- internal/bundler/vercel_ai.go | 2 +- 7 files changed, 136 insertions(+), 77 deletions(-) diff --git a/cmd/cloud.go b/cmd/cloud.go index 42dfe690..b142de93 100644 --- a/cmd/cloud.go +++ b/cmd/cloud.go @@ -15,7 +15,6 @@ import ( "time" "github.com/agentuity/cli/internal/agent" - "github.com/agentuity/cli/internal/bundler" "github.com/agentuity/cli/internal/deployer" "github.com/agentuity/cli/internal/errsystem" "github.com/agentuity/cli/internal/ignore" @@ -114,14 +113,7 @@ func ShowNewProjectImport(ctx context.Context, logger logger.Logger, cmd *cobra. errsystem.New(errsystem.ErrSaveProject, err, errsystem.WithContextMessage("Error saving project after import")).ShowErrorAndExit() } - saveEnv(bundler.BundleContext{ - Context: ctx, - Logger: logger, - ProjectDir: dir, - Production: true, // TODO: need to come back and look at this - Install: false, - CI: false, - }, dir, result.APIKey, result.ProjectKey, project.Bundler.Language) + saveEnv(dir, result.APIKey, result.ProjectKey) }) tui.ShowSuccess("Project imported successfully") } diff --git a/cmd/project.go b/cmd/project.go index ad5bf095..244ebc9a 100644 --- a/cmd/project.go +++ b/cmd/project.go @@ -11,8 +11,6 @@ import ( "sort" "syscall" - "github.com/Masterminds/semver" - "github.com/agentuity/cli/internal/bundler" "github.com/agentuity/cli/internal/errsystem" "github.com/agentuity/cli/internal/mcp" "github.com/agentuity/cli/internal/organization" @@ -38,16 +36,9 @@ Use the subcommands to manage your projects.`, }, } -func saveEnv(bcxt bundler.BundleContext, dir string, apikey string, projectKey string, language string) { +func saveEnv(dir string, apikey string, projectKey string) { filename := filepath.Join(dir, ".env") envLines, err := env.ParseEnvFile(filename) - version, err := bundler.GetSDKVersion(language, bcxt) - - versions := map[string]string{ - "python": "0.0.83", - "javascript": "0.0.114", - } - if err != nil { errsystem.New(errsystem.ErrReadConfigurationFile, err, errsystem.WithContextMessage("Failed to parse .env file")).ShowErrorAndExit() } @@ -72,8 +63,7 @@ func saveEnv(bcxt bundler.BundleContext, dir string, apikey string, projectKey s } } - gtVersion := version.GreaterThan(semver.MustParse(versions[language])) - if gtVersion && found["AGENTUITY_API_KEY"] { + if found["AGENTUITY_API_KEY"] { // Remove AGENTUITY_API_KEY since it's deprecated in newer SDK versions for i := len(envLines) - 1; i >= 0; i-- { if envLines[i].Key == "AGENTUITY_API_KEY" { @@ -82,13 +72,13 @@ func saveEnv(bcxt bundler.BundleContext, dir string, apikey string, projectKey s } found["AGENTUITY_API_KEY"] = false } - if !found["AGENTUITY_API_KEY"] && !gtVersion { - envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_API_KEY", Val: apikey}) - } if !found["AGENTUITY_SDK_KEY"] { envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_SDK_KEY", Val: apikey}) } + if !found["AGENTUITY_PROJECT_KEY"] { + envLines = append(envLines, env.EnvLine{Key: "AGENTUITY_PROJECT_KEY", Val: projectKey}) + } if err := env.WriteEnvFile(filename, envLines); err != nil { errsystem.New(errsystem.ErrWriteConfigurationFile, err, errsystem.WithContextMessage("Failed to write .env file")).ShowErrorAndExit() @@ -166,14 +156,7 @@ func initProject(ctx context.Context, logger logger.Logger, args InitProjectArgs errsystem.New(errsystem.ErrSaveProject, err, errsystem.WithContextMessage("Failed to save project to disk")).ShowErrorAndExit() } - saveEnv(bundler.BundleContext{ - Context: ctx, - Logger: logger, - ProjectDir: args.Dir, - Production: true, // TODO: need to come back and look at this - Install: false, - CI: false, - }, args.Dir, result.APIKey, result.ProjectKey, proj.Bundler.Language) + saveEnv(args.Dir, result.APIKey, result.ProjectKey) return result } diff --git a/internal/bundler/anthropic.go b/internal/bundler/anthropic.go index 904f6206..111c13cb 100644 --- a/internal/bundler/anthropic.go +++ b/internal/bundler/anthropic.go @@ -5,7 +5,7 @@ func init() { Module: "@anthropic-ai", Filename: "sdk\\/index.*", Body: &patchAction{ - Before: generateEnvGuard("ANTHROPIC_API_KEY", generateGatewayEnvGuard("ANTHROPIC_API_KEY", "process.env.AGENTUITY_API_KEY || process.env.AGENTUITY_SDK_KEY", "ANTHROPIC_BASE_URL", "anthropic")), + Before: generateEnvGuard("ANTHROPIC_API_KEY", generateGatewayEnvGuard("ANTHROPIC_API_KEY", "process.env.AGENTUITY_SDK_KEY", "ANTHROPIC_BASE_URL", "anthropic")), }, } } diff --git a/internal/bundler/openai.go b/internal/bundler/openai.go index 3c6ac7a1..e0e1fde3 100644 --- a/internal/bundler/openai.go +++ b/internal/bundler/openai.go @@ -5,7 +5,7 @@ func init() { Module: "openai", Filename: "index", Body: &patchAction{ - Before: generateEnvGuard("OPENAI_API_KEY", generateGatewayEnvGuard("OPENAI_API_KEY", "process.env.AGENTUITY_API_KEY || process.env.AGENTUITY_SDK_KEY", "OPENAI_BASE_URL", "openai")), + Before: generateEnvGuard("OPENAI_API_KEY", generateGatewayEnvGuard("OPENAI_API_KEY", "process.env.AGENTUITY_SDK_KEY", "OPENAI_BASE_URL", "openai")), }, } } diff --git a/internal/bundler/patch.go b/internal/bundler/patch.go index eecc5542..a1a3e1ce 100644 --- a/internal/bundler/patch.go +++ b/internal/bundler/patch.go @@ -37,14 +37,14 @@ _args = _newargs;`, index, inject) } func generateEnvGuard(name string, inject string) string { - return fmt.Sprintf(`if (!process.env.%[1]s || process.env.%[1]s === (process.env.AGENTUITY_API_KEY || process.env.AGENTUITY_SDK_KEY)) { + return fmt.Sprintf(`if (!process.env.%[1]s || process.env.%[1]s === process.env.AGENTUITY_SDK_KEY) { %[2]s }`, name, inject) } func generateGatewayEnvGuard(apikey string, apikeyval string, apibase string, provider string) string { return fmt.Sprintf(`{ - const apikey = process.env.AGENTUITY_API_KEY || process.env.AGENTUITY_SDK_KEY; + const apikey = process.env.AGENTUITY_SDK_KEY; const url = process.env.AGENTUITY_TRANSPORT_URL; if (url && apikey) { process.env.%[1]s = %[2]s; diff --git a/internal/bundler/upgrade.go b/internal/bundler/upgrade.go index e488a52c..4d001d38 100644 --- a/internal/bundler/upgrade.go +++ b/internal/bundler/upgrade.go @@ -14,10 +14,11 @@ import ( ) type breakingChange struct { - Title string - Message string - Runtime string - Version string + Title string + Message string + Runtime string + Version string + Callback func(ctx BundleContext) error } var breakingChanges = []breakingChange{ @@ -39,6 +40,96 @@ var breakingChanges = []breakingChange{ Title: "🚫 Python SDK Breaking Changes 🚫", Message: "The Python SDK type signatures for AgentRequest have changed to be async functions. Please see the v0.0.82 Changelog for how to update your code.\n\n" + tui.Link("https://agentuity.dev/Changelog/sdk-py#v0082") + "\n\nPlease run `uv add agentuity -U` fix your types and ensure your code passes type checking and then re-run this command again.", }, + { + Runtime: "bunjs", + Version: "<0.0.115", + Title: "🚫 JS SDK Breaking Change 🚫", + Message: "The environment variable and code reference for your Agentuity API key has changed from AGENTUITY_API_KEY to AGENTUITY_SDK_KEY. Update all occurrences in your .env files and codebase. See the v0.0.114 Changelog for details.\n\n" + tui.Link("https://agentuity.dev/Changelog/sdk-js#v00114") + "\n\nAfter migrated, please run bun update @agentuity/sdk --latest and then re-run this command again.", + Callback: func(ctx BundleContext) error { + files := []string{ + filepath.Join(ctx.ProjectDir, "index.ts"), + filepath.Join(ctx.ProjectDir, ".env"), + } + for _, file := range files { + if !util.Exists(file) { + continue + } + content, err := os.ReadFile(file) + if err != nil { + return err + } + updated := strings.ReplaceAll(string(content), `AGENTUITY_API_KEY`, `AGENTUITY_SDK_KEY`) + if updated != string(content) { + err = os.WriteFile(file, []byte(updated), 0644) + if err != nil { + return err + } + } + } + + return nil + }, + }, + { + Runtime: "nodejs", + Version: "<0.0.115 ", + Title: "🚫 JS SDK Breaking Change 🚫", + Message: "The environment variable and code reference for your Agentuity API key has changed from AGENTUITY_API_KEY to AGENTUITY_SDK_KEY. Update all occurrences in your .env files and codebase. See the v0.0.114 Changelog for details.\n\n" + tui.Link("https://agentuity.dev/Changelog/sdk-js#v00114") + "\n\nAfter migrated, please run npm i @agentuity/sdk --latest and then re-run this command again.", + Callback: func(ctx BundleContext) error { + files := []string{ + filepath.Join(ctx.ProjectDir, "index.ts"), + filepath.Join(ctx.ProjectDir, ".env"), + } + for _, file := range files { + if !util.Exists(file) { + continue + } + content, err := os.ReadFile(file) + if err != nil { + return err + } + updated := strings.ReplaceAll(string(content), `AGENTUITY_API_KEY`, `AGENTUITY_SDK_KEY`) + if updated != string(content) { + err = os.WriteFile(file, []byte(updated), 0644) + if err != nil { + return err + } + } + } + + return nil + }, + }, + { + Runtime: "uv", + Version: "<0.0.84", + Title: "🚫 Python SDK Breaking Changes 🚫", + Message: "The environment variable and code reference for your Agentuity API key has changed from AGENTUITY_API_KEY to AGENTUITY_SDK_KEY. Update all occurrences in your .env files and codebase. See the v0.0.114 Changelog for details.\n\n" + tui.Link("https://agentuity.dev/Changelog/sdk-js#v00114") + "\n\nAfter migrated, please run `uv add agentuity -U` --latest and then re-run this command again.", + Callback: func(ctx BundleContext) error { + files := []string{ + filepath.Join(ctx.ProjectDir, "server.py"), + filepath.Join(ctx.ProjectDir, ".env"), + } + for _, file := range files { + if !util.Exists(file) { + continue + } + content, err := os.ReadFile(file) + if err != nil { + return err + } + updated := strings.ReplaceAll(string(content), `AGENTUITY_API_KEY`, `AGENTUITY_SDK_KEY`) + if updated != string(content) { + err = os.WriteFile(file, []byte(updated), 0644) + if err != nil { + return err + } + } + } + + return nil + }, + }, } type packageJSON struct { @@ -107,46 +198,40 @@ func GetSDKVersion(language string, ctx BundleContext) (*semver.Version, error) func checkForBreakingChanges(ctx BundleContext, language string, runtime string) error { ctx.Logger.Trace("Checking for breaking changes in %s, runtime: %s", language, runtime) - switch language { - case "python": - currentVersion, err := getSDKVersionPython(ctx) + currentVersion, err := GetSDKVersion(language, ctx) + if err != nil { + return err + } + for _, change := range breakingChanges { + if change.Runtime != runtime { + continue + } + c, err := semver.NewConstraint(change.Version) if err != nil { - return err + return fmt.Errorf("error parsing semver constraint %s: %w", change.Version, err) } - for _, change := range breakingChanges { - if change.Runtime != runtime { - continue - } - c, err := semver.NewConstraint(change.Version) - if err != nil { - return fmt.Errorf("error parsing semver constraint %s: %w", change.Version, err) - } - if c.Check(currentVersion) { + if strings.Contains(currentVersion.String(), "-pre") { + return nil + } + if c.Check(currentVersion) { + if change.Callback != nil { + var proceed bool if tui.HasTTY { tui.ShowBanner(change.Title, change.Message, true) - os.Exit(1) } else { - ctx.Logger.Fatal(change.Message) + tui.Text(change.Title + " - " + change.Message) + return fmt.Errorf("migration required") } - } - } - case "javascript": - currentVersion, err := getSDKVersionJavascript(ctx) - if err != nil { - return err - } - for _, change := range breakingChanges { - if change.Runtime != runtime { - continue - } - c, err := semver.NewConstraint(change.Version) - if err != nil { - return fmt.Errorf("error parsing semver constraint %s: %w", change.Version, err) - } - if strings.Contains(currentVersion.String(), "-pre") { - return nil - } - if c.Check(currentVersion) { + proceed = tui.AskForConfirm("Would you like to migrate your project now?", 'y') == 'y' + if proceed { + if err := change.Callback(ctx); err != nil { + return err + } + return nil + } else { + return fmt.Errorf("migration required") + } + } else { if tui.HasTTY { tui.ShowBanner(change.Title, change.Message, true) os.Exit(1) @@ -155,8 +240,7 @@ func checkForBreakingChanges(ctx BundleContext, language string, runtime string) } } } - default: - return nil } + return nil } diff --git a/internal/bundler/vercel_ai.go b/internal/bundler/vercel_ai.go index 0c34b9cc..3fbea7c1 100644 --- a/internal/bundler/vercel_ai.go +++ b/internal/bundler/vercel_ai.go @@ -5,7 +5,7 @@ import "fmt" func generateVercelAIProvider(name string, envkey string) string { return generateJSArgsPatch(0, "") + fmt.Sprintf(`const opts = {...(_args[0] ?? {}) }; if (!opts.baseURL) { - const apikey = process.env.AGENTUITY_API_KEY || process.env.AGENTUITY_SDK_KEY; + const apikey = process.env.AGENTUITY_SDK_KEY; const url = process.env.AGENTUITY_TRANSPORT_URL; if (url && apikey) { opts.apiKey = apikey; From 16196d5fd373f930a6fa7f283365b3fea8ccdd5e Mon Sep 17 00:00:00 2001 From: Bobby Christopher Date: Tue, 13 May 2025 13:33:40 -0400 Subject: [PATCH 09/13] added version --- internal/bundler/upgrade.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/bundler/upgrade.go b/internal/bundler/upgrade.go index 4d001d38..ecfbfdc5 100644 --- a/internal/bundler/upgrade.go +++ b/internal/bundler/upgrade.go @@ -44,7 +44,7 @@ var breakingChanges = []breakingChange{ Runtime: "bunjs", Version: "<0.0.115", Title: "🚫 JS SDK Breaking Change 🚫", - Message: "The environment variable and code reference for your Agentuity API key has changed from AGENTUITY_API_KEY to AGENTUITY_SDK_KEY. Update all occurrences in your .env files and codebase. See the v0.0.114 Changelog for details.\n\n" + tui.Link("https://agentuity.dev/Changelog/sdk-js#v00114") + "\n\nAfter migrated, please run bun update @agentuity/sdk --latest and then re-run this command again.", + Message: "The environment variable and code reference for your Agentuity API key has changed from AGENTUITY_API_KEY to AGENTUITY_SDK_KEY. Update all occurrences in your .env files and codebase. See the v0.0.115 Changelog for details.\n\n" + tui.Link("https://agentuity.dev/Changelog/sdk-js#v00114") + "\n\nAfter migrated, please run bun update @agentuity/sdk --latest and then re-run this command again.", Callback: func(ctx BundleContext) error { files := []string{ filepath.Join(ctx.ProjectDir, "index.ts"), @@ -74,7 +74,7 @@ var breakingChanges = []breakingChange{ Runtime: "nodejs", Version: "<0.0.115 ", Title: "🚫 JS SDK Breaking Change 🚫", - Message: "The environment variable and code reference for your Agentuity API key has changed from AGENTUITY_API_KEY to AGENTUITY_SDK_KEY. Update all occurrences in your .env files and codebase. See the v0.0.114 Changelog for details.\n\n" + tui.Link("https://agentuity.dev/Changelog/sdk-js#v00114") + "\n\nAfter migrated, please run npm i @agentuity/sdk --latest and then re-run this command again.", + Message: "The environment variable and code reference for your Agentuity API key has changed from AGENTUITY_API_KEY to AGENTUITY_SDK_KEY. Update all occurrences in your .env files and codebase. See the v0.0.115 Changelog for details.\n\n" + tui.Link("https://agentuity.dev/Changelog/sdk-js#v00114") + "\n\nAfter migrated, please run npm i @agentuity/sdk --latest and then re-run this command again.", Callback: func(ctx BundleContext) error { files := []string{ filepath.Join(ctx.ProjectDir, "index.ts"), @@ -104,7 +104,7 @@ var breakingChanges = []breakingChange{ Runtime: "uv", Version: "<0.0.84", Title: "🚫 Python SDK Breaking Changes 🚫", - Message: "The environment variable and code reference for your Agentuity API key has changed from AGENTUITY_API_KEY to AGENTUITY_SDK_KEY. Update all occurrences in your .env files and codebase. See the v0.0.114 Changelog for details.\n\n" + tui.Link("https://agentuity.dev/Changelog/sdk-js#v00114") + "\n\nAfter migrated, please run `uv add agentuity -U` --latest and then re-run this command again.", + Message: "The environment variable and code reference for your Agentuity API key has changed from AGENTUITY_API_KEY to AGENTUITY_SDK_KEY. Update all occurrences in your .env files and codebase. See the v0.0.84 Changelog for details.\n\n" + tui.Link("https://agentuity.dev/Changelog/python-js#v0084") + "\n\nAfter migrated, please run `uv add agentuity -U` --latest and then re-run this command again.", Callback: func(ctx BundleContext) error { files := []string{ filepath.Join(ctx.ProjectDir, "server.py"), From f110244902d66e50988621b640b4cfe4044744e7 Mon Sep 17 00:00:00 2001 From: Bobby Christopher Date: Tue, 13 May 2025 16:49:24 -0400 Subject: [PATCH 10/13] exit after migration --- internal/bundler/upgrade.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/bundler/upgrade.go b/internal/bundler/upgrade.go index ecfbfdc5..0ce5885e 100644 --- a/internal/bundler/upgrade.go +++ b/internal/bundler/upgrade.go @@ -227,7 +227,7 @@ func checkForBreakingChanges(ctx BundleContext, language string, runtime string) if err := change.Callback(ctx); err != nil { return err } - return nil + os.Exit(1) } else { return fmt.Errorf("migration required") } From 96f4d9231aea3e8c880303cf0db7f8404a24e048 Mon Sep 17 00:00:00 2001 From: Bobby Christopher Date: Tue, 13 May 2025 18:44:54 -0400 Subject: [PATCH 11/13] added right link --- internal/bundler/upgrade.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/bundler/upgrade.go b/internal/bundler/upgrade.go index 0ce5885e..78f0d424 100644 --- a/internal/bundler/upgrade.go +++ b/internal/bundler/upgrade.go @@ -44,7 +44,7 @@ var breakingChanges = []breakingChange{ Runtime: "bunjs", Version: "<0.0.115", Title: "🚫 JS SDK Breaking Change 🚫", - Message: "The environment variable and code reference for your Agentuity API key has changed from AGENTUITY_API_KEY to AGENTUITY_SDK_KEY. Update all occurrences in your .env files and codebase. See the v0.0.115 Changelog for details.\n\n" + tui.Link("https://agentuity.dev/Changelog/sdk-js#v00114") + "\n\nAfter migrated, please run bun update @agentuity/sdk --latest and then re-run this command again.", + Message: "The environment variable and code reference for your Agentuity API key has changed from AGENTUITY_API_KEY to AGENTUITY_SDK_KEY. Update all occurrences in your .env files and codebase. See the v0.0.115 Changelog for details.\n\n" + tui.Link("https://agentuity.dev/Changelog/sdk-js#v00115") + "\n\nAfter migrated, please run bun update @agentuity/sdk --latest and then re-run this command again.", Callback: func(ctx BundleContext) error { files := []string{ filepath.Join(ctx.ProjectDir, "index.ts"), @@ -74,7 +74,7 @@ var breakingChanges = []breakingChange{ Runtime: "nodejs", Version: "<0.0.115 ", Title: "🚫 JS SDK Breaking Change 🚫", - Message: "The environment variable and code reference for your Agentuity API key has changed from AGENTUITY_API_KEY to AGENTUITY_SDK_KEY. Update all occurrences in your .env files and codebase. See the v0.0.115 Changelog for details.\n\n" + tui.Link("https://agentuity.dev/Changelog/sdk-js#v00114") + "\n\nAfter migrated, please run npm i @agentuity/sdk --latest and then re-run this command again.", + Message: "The environment variable and code reference for your Agentuity API key has changed from AGENTUITY_API_KEY to AGENTUITY_SDK_KEY. Update all occurrences in your .env files and codebase. See the v0.0.115 Changelog for details.\n\n" + tui.Link("https://agentuity.dev/Changelog/sdk-js#v00115") + "\n\nAfter migrated, please run npm i @agentuity/sdk --latest and then re-run this command again.", Callback: func(ctx BundleContext) error { files := []string{ filepath.Join(ctx.ProjectDir, "index.ts"), From 6a5e9e10a7b16dc2a06c6aa2349b46180b6b04a3 Mon Sep 17 00:00:00 2001 From: Bobby Christopher Date: Wed, 14 May 2025 08:51:04 -0400 Subject: [PATCH 12/13] Update cmd/project.go Co-authored-by: Robin Diddams --- cmd/project.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/project.go b/cmd/project.go index 244ebc9a..c0ce4cfc 100644 --- a/cmd/project.go +++ b/cmd/project.go @@ -42,7 +42,7 @@ func saveEnv(dir string, apikey string, projectKey string) { if err != nil { errsystem.New(errsystem.ErrReadConfigurationFile, err, errsystem.WithContextMessage("Failed to parse .env file")).ShowErrorAndExit() } - var found map[string]bool = map[string]bool{ + found := map[string]bool{ "AGENTUITY_SDK_KEY": false, "AGENTUITY_API_KEY": false, "AGENTUITY_PROJECT_KEY": false, From cfa19ffc7f9313ca5619e43243cc9fec7ce425b4 Mon Sep 17 00:00:00 2001 From: Bobby Christopher Date: Wed, 14 May 2025 08:51:20 -0400 Subject: [PATCH 13/13] Update cmd/project.go Co-authored-by: Robin Diddams --- cmd/project.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/project.go b/cmd/project.go index c0ce4cfc..dd1c23c8 100644 --- a/cmd/project.go +++ b/cmd/project.go @@ -55,11 +55,11 @@ func saveEnv(dir string, apikey string, projectKey string) { } if envLine.Key == "AGENTUITY_SDK_KEY" { envLines[i].Val = apikey - found["AGENTUITY_SDK_KEY"] = true + found[envLine.Key] = true } if envLine.Key == "AGENTUITY_PROJECT_KEY" { envLines[i].Val = projectKey - found["AGENTUITY_PROJECT_KEY"] = true + found[envLine.Key] = true } }