From 08e44decfe697f6efb675f05ba13dd2e0e56aa91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Da=CC=81vid=20Istva=CC=81n=20Bi=CC=81ro=CC=81?= Date: Fri, 24 Apr 2026 12:07:48 +0200 Subject: [PATCH 1/2] agent type listing and get cleanup --- cli/golem-cli/src/command.rs | 50 +++++++++++++++++-- cli/golem-cli/src/command_handler/app/mod.rs | 27 ++++++++++ cli/golem-cli/src/command_handler/mod.rs | 15 ++++-- .../tests/app/build_and_deploy_all.rs | 4 +- cli/golem-cli/tests/app/mod.rs | 2 +- .../scenarios/change-durability-mode.yaml | 4 +- .../harness/scenarios/stateless-agent.yaml | 2 +- 7 files changed, 93 insertions(+), 11 deletions(-) diff --git a/cli/golem-cli/src/command.rs b/cli/golem-cli/src/command.rs index a95b9f8556..d79b868c88 100644 --- a/cli/golem-cli/src/command.rs +++ b/cli/golem-cli/src/command.rs @@ -15,6 +15,7 @@ use self::api::agent_secret::AgentSecretSubcommand; use self::api::resource_definition::ResourceDefinitionSubcommand; use self::api::retry_policy::RetryPolicySubcommand; +use crate::command::agent_type::AgentTypeSubcommand; use crate::app::template::AppTemplateName; use crate::command::api::ApiSubcommand; use crate::command::cloud::CloudSubcommand; @@ -709,9 +710,6 @@ pub enum GolemCliSubcommand { #[command(flatten)] component_name: OptionalComponentNames, }, - /// List all the deployed agent types - ListAgentTypes {}, - // Other entities ------------------------------------------------------------------------------ /// Execute custom, application manifest defined commands Exec { @@ -733,6 +731,11 @@ pub enum GolemCliSubcommand { #[clap(subcommand)] subcommand: AgentSubcommand, }, + /// Manage deployed agent types + AgentType { + #[clap(subcommand)] + subcommand: AgentTypeSubcommand, + }, /// Manage API gateway objects Api { #[clap(subcommand)] @@ -1276,6 +1279,22 @@ pub mod worker { } } +pub mod agent_type { + use clap::Subcommand; + use golem_common::model::agent::AgentTypeName; + + #[derive(Debug, Subcommand)] + pub enum AgentTypeSubcommand { + /// List all deployed agent types + List, + /// Get deployed agent type metadata + Get { + /// Agent type name + agent_type_name: AgentTypeName, + }, + } +} + pub mod api { use crate::command::api::deployment::ApiDeploymentSubcommand; use crate::command::api::domain::ApiDomainSubcommand; @@ -1899,6 +1918,7 @@ pub fn help_target_to_command(target: ShowClapHelpTarget) -> Command { #[cfg(test)] mod test { + use crate::command::agent_type::AgentTypeSubcommand; use crate::command::api::agent_secret::AgentSecretSubcommand; use crate::command::{ GolemCliCommand, GolemCliSubcommand, builtin_exec_subcommands, @@ -1932,6 +1952,30 @@ mod test { )); } + #[test] + fn agent_type_list_parses() { + let command = GolemCliCommand::try_parse_from(["golem", "agent-type", "list"]) + .expect("command should parse"); + + let GolemCliSubcommand::AgentType { subcommand } = command.subcommand else { + panic!("expected agent-type subcommand"); + }; + + assert!(matches!(subcommand, AgentTypeSubcommand::List)); + } + + #[test] + fn agent_type_get_parses() { + let command = GolemCliCommand::try_parse_from(["golem", "agent-type", "get", "CounterAgent"]) + .expect("command should parse"); + + let GolemCliSubcommand::AgentType { subcommand } = command.subcommand else { + panic!("expected agent-type subcommand"); + }; + + assert!(matches!(subcommand, AgentTypeSubcommand::Get { .. })); + } + #[test] fn all_commands_and_args_has_doc() { fn collect_docs( diff --git a/cli/golem-cli/src/command_handler/app/mod.rs b/cli/golem-cli/src/command_handler/app/mod.rs index e5886d7ad0..fbe8c305a9 100644 --- a/cli/golem-cli/src/command_handler/app/mod.rs +++ b/cli/golem-cli/src/command_handler/app/mod.rs @@ -37,6 +37,7 @@ use crate::log::{ log_finished_ok, log_finished_up_to_date, log_skipping_up_to_date, log_warn, log_warn_action, logged_failed_to, logged_finished_or_failed_to, logln, }; +use crate::model::agent::view::AgentTypeView; use crate::model::GuestLanguage; use crate::model::app::{ AppBuildStep, ApplicationComponentSelectMode, BuildConfig, CleanMode, DynamicHelpSections, @@ -59,6 +60,7 @@ use futures_util::{StreamExt, TryStreamExt, stream}; use golem_client::api::{ApplicationClient, ComponentClient, EnvironmentClient}; use golem_client::model::{ApplicationCreation, DeploymentCreation, DeploymentRollback}; use golem_common::model::account::AccountId; +use golem_common::model::agent::AgentTypeName; use golem_common::model::agent::DeployedRegisteredAgentType; use golem_common::model::agent::schema_evolution::validate_schema_evolution; use golem_common::model::application::ApplicationName; @@ -414,6 +416,31 @@ impl AppCommandHandler { Ok(()) } + pub async fn cmd_get_agent_type(&self, agent_type_name: AgentTypeName) -> anyhow::Result<()> { + let environment = self + .ctx + .environment_handler() + .resolve_environment(EnvironmentResolveMode::Any) + .await?; + + let Some(agent_type) = self + .get_agent_type_by_name(&environment, agent_type_name.0.as_str()) + .await? + else { + log_error(format!( + "Agent type {} not found", + agent_type_name.0.log_color_highlight() + )); + bail!(NonSuccessfulExit); + }; + + self.ctx + .log_handler() + .log_view(&AgentTypeView::new(&agent_type, true)); + + Ok(()) + } + pub async fn list_agent_types( &self, environment: &ResolvedEnvironmentIdentity, diff --git a/cli/golem-cli/src/command_handler/mod.rs b/cli/golem-cli/src/command_handler/mod.rs index e5483255c6..ab3b2cf612 100644 --- a/cli/golem-cli/src/command_handler/mod.rs +++ b/cli/golem-cli/src/command_handler/mod.rs @@ -15,6 +15,7 @@ use self::agent_secret::AgentSecretCommandHandler; use self::resource_definition::ResourceDefinitionCommandHandler; use self::retry_policy::RetryPolicyCommandHandler; +use crate::command::agent_type::AgentTypeSubcommand; #[cfg(feature = "server-commands")] use crate::command::server::ServerSubcommand; use crate::command::{ @@ -364,9 +365,6 @@ impl CommandHandler { .cmd_redeploy_workers(component_name.component_name) .await } - GolemCliSubcommand::ListAgentTypes {} => { - self.ctx.app_handler().cmd_list_agent_types().await - } GolemCliSubcommand::Exec { subcommand } => { self.ctx.app_handler().exec_custom_command(subcommand).await } @@ -387,6 +385,17 @@ impl CommandHandler { GolemCliSubcommand::Agent { subcommand } => { self.ctx.worker_handler().handle_command(subcommand).await } + GolemCliSubcommand::AgentType { subcommand } => match subcommand { + AgentTypeSubcommand::List => { + self.ctx.app_handler().cmd_list_agent_types().await + } + AgentTypeSubcommand::Get { agent_type_name } => { + self.ctx + .app_handler() + .cmd_get_agent_type(agent_type_name) + .await + } + }, GolemCliSubcommand::Api { subcommand } => { self.ctx.api_handler().handle_command(subcommand).await } diff --git a/cli/golem-cli/tests/app/build_and_deploy_all.rs b/cli/golem-cli/tests/app/build_and_deploy_all.rs index ee80ce1802..b939b0bb33 100644 --- a/cli/golem-cli/tests/app/build_and_deploy_all.rs +++ b/cli/golem-cli/tests/app/build_and_deploy_all.rs @@ -72,7 +72,9 @@ async fn build_and_deploy_all_templates_for_lang(language: GuestLanguage) { let outputs = ctx.cli([cmd::DEPLOY, flag::YES]).await; assert!(outputs.success_or_dump()); - let outputs = ctx.cli([cmd::LIST_AGENT_TYPES, flag::FORMAT, "json"]).await; + let outputs = ctx + .cli([cmd::AGENT_TYPE, cmd::LIST, flag::FORMAT, "json"]) + .await; let deployed_agent_types = outputs .stdout_json::>() .into_iter() diff --git a/cli/golem-cli/tests/app/mod.rs b/cli/golem-cli/tests/app/mod.rs index d710c2f602..6b6830ed87 100644 --- a/cli/golem-cli/tests/app/mod.rs +++ b/cli/golem-cli/tests/app/mod.rs @@ -67,6 +67,7 @@ mod cmd { pub static NO_ARGS: &[&str] = &[]; pub static AGENT: &str = "agent"; + pub static AGENT_TYPE: &str = "agent-type"; pub static BUILD: &str = "build"; pub static COMPLETION: &str = "completion"; pub static COMPONENT: &str = "component"; @@ -75,7 +76,6 @@ mod cmd { pub static GET: &str = "get"; pub static INVOKE: &str = "invoke"; pub static LIST: &str = "list"; - pub static LIST_AGENT_TYPES: &str = "list-agent-types"; pub static NEW: &str = "new"; pub static PLUGIN: &str = "plugin"; pub static REGISTER: &str = "register"; diff --git a/golem-skills/tests/harness/scenarios/change-durability-mode.yaml b/golem-skills/tests/harness/scenarios/change-durability-mode.yaml index 0c12429aa6..d99d0e24db 100644 --- a/golem-skills/tests/harness/scenarios/change-durability-mode.yaml +++ b/golem-skills/tests/harness/scenarios/change-durability-mode.yaml @@ -26,7 +26,7 @@ steps: - id: "verify-ephemeral" shell: command: "golem" - args: ["list-agent-types", "--environment", "test-app/local", "--format", "json"] + args: ["agent-type", "list", "--environment", "test-app/local", "--format", "json"] expect: exit_code: 0 stdout_contains: '"mode":"Ephemeral"' @@ -50,7 +50,7 @@ steps: - id: "verify-durable" shell: command: "golem" - args: ["list-agent-types", "--environment", "test-app/local", "--format", "json"] + args: ["agent-type", "list", "--environment", "test-app/local", "--format", "json"] expect: exit_code: 0 stdout_contains: '"mode":"Durable"' diff --git a/golem-skills/tests/harness/scenarios/stateless-agent.yaml b/golem-skills/tests/harness/scenarios/stateless-agent.yaml index 6ddec7cdf9..66f46190b9 100644 --- a/golem-skills/tests/harness/scenarios/stateless-agent.yaml +++ b/golem-skills/tests/harness/scenarios/stateless-agent.yaml @@ -54,7 +54,7 @@ steps: - id: "verify-ephemeral-mode" shell: command: "golem" - args: ["list-agent-types", "--environment", "test-app/local", "--format", "json"] + args: ["agent-type", "list", "--environment", "test-app/local", "--format", "json"] expect: exit_code: 0 stdout_contains: '"mode":"Ephemeral"' From 95825fb2e5be540ebb895077f61acc54556ac852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Da=CC=81vid=20Istva=CC=81n=20Bi=CC=81ro=CC=81?= Date: Fri, 24 Apr 2026 12:47:43 +0200 Subject: [PATCH 2/2] doc comment, naming and module cleanups --- cli/golem-cli/src/command.rs | 384 ++++++++---------- cli/golem-cli/src/command_handler/app/mod.rs | 2 +- .../src/command_handler/partial_match.rs | 6 +- .../command_handler/resource_definition.rs | 2 +- .../src/command_handler/retry_policy.rs | 2 +- .../src/command_handler/worker/mod.rs | 34 +- cli/golem-cli/src/model/text/help.rs | 4 +- 7 files changed, 197 insertions(+), 237 deletions(-) diff --git a/cli/golem-cli/src/command.rs b/cli/golem-cli/src/command.rs index d79b868c88..bffeb7b3ae 100644 --- a/cli/golem-cli/src/command.rs +++ b/cli/golem-cli/src/command.rs @@ -12,18 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -use self::api::agent_secret::AgentSecretSubcommand; -use self::api::resource_definition::ResourceDefinitionSubcommand; -use self::api::retry_policy::RetryPolicySubcommand; -use crate::command::agent_type::AgentTypeSubcommand; use crate::app::template::AppTemplateName; +use crate::command::agent_type::AgentTypeSubcommand; use crate::command::api::ApiSubcommand; +use crate::command::api::agent_secret::AgentSecretSubcommand; use crate::command::cloud::CloudSubcommand; use crate::command::component::ComponentSubcommand; use crate::command::environment::EnvironmentSubcommand; use crate::command::exec::ExecSubcommand; use crate::command::plugin::PluginSubcommand; use crate::command::profile::ProfileSubcommand; +use crate::command::resource_definition::ResourceDefinitionSubcommand; +use crate::command::retry_policy::RetryPolicySubcommand; #[cfg(feature = "server-commands")] use crate::command::server::ServerSubcommand; use crate::command::shared_args::{ @@ -191,7 +191,7 @@ pub struct GolemCliGlobalFlags { #[arg(long, short = 'Y', global = true, display_order = 110)] pub yes: bool, - /// Disables filtering of potentially sensitive use values in text mode (e.g. component environment variable values) + /// Disables filtering of potentially sensitive user values in text mode (e.g. component environment variable values) #[arg(long, global = true, display_order = 111)] pub show_sensitive: bool, @@ -477,7 +477,7 @@ impl GolemCliCommand { subcommands: vec!["agent", "invoke"], found_positional_args: vec![], missing_positional_arg: "agent_id", - to_partial_match: |_| GolemCliCommandPartialMatch::WorkerInvokeMissingWorkerName, + to_partial_match: |_| GolemCliCommandPartialMatch::AgentInvokeMissingAgentName, }, InvalidArgMatcher { subcommands: vec!["agent", "invoke"], @@ -588,7 +588,7 @@ pub enum GolemCliCommandPartialMatch { ComponentMissingSubcommandHelp, AgentHelp, AgentInvokeMissingFunctionName { agent_name: RawAgentId }, - WorkerInvokeMissingWorkerName, + AgentInvokeMissingAgentName, ProfileSwitchMissingProfileName, } @@ -762,12 +762,12 @@ pub enum GolemCliSubcommand { #[clap(subcommand)] subcommand: CloudSubcommand, }, - /// Manage Agent Secrets + /// Manage agent secrets AgentSecret { #[clap(subcommand)] subcommand: AgentSecretSubcommand, }, - /// Manage Retry Policies + /// Manage retry policies RetryPolicy { #[clap(subcommand)] subcommand: RetryPolicySubcommand, @@ -779,7 +779,7 @@ pub enum GolemCliSubcommand { }, /// Generate shell completion Completion { - /// Selects shell + /// Select shell shell: clap_complete::Shell, }, } @@ -793,9 +793,9 @@ pub mod shared_args { use golem_common::model::component::ComponentName; pub type ComponentTemplateName = String; - pub type NewWorkerArgument = String; - pub type WorkerFunctionArgument = String; - pub type WorkerFunctionName = String; + pub type NewAgentArgument = String; + pub type AgentFunctionArgument = String; + pub type AgentFunctionName = String; #[derive(Debug, Args)] pub struct OptionalComponentName { @@ -1046,13 +1046,14 @@ pub mod worker { use crate::args::parse_cursor; use crate::args::parse_key_val; use crate::command::shared_args::{ - AgentIdArgs, PostDeployArgs, StreamArgs, WorkerFunctionArgument, WorkerFunctionName, + AgentFunctionArgument, AgentFunctionName, AgentIdArgs, PostDeployArgs, StreamArgs, }; use crate::model::worker::AgentUpdateMode; use chrono::{DateTime, Utc}; use clap::Subcommand; use golem_client::model::ScanCursor; use golem_common::model::IdempotencyKey; + use golem_common::model::agent::AgentTypeName; use golem_common::model::component::{ComponentName, ComponentRevision}; use golem_common::model::worker::AgentConfigEntryDto; use uuid::Uuid; @@ -1067,7 +1068,7 @@ pub mod worker { #[arg(short, long, value_parser = parse_key_val, value_name = "ENV=VAL")] env: Vec<(String, String)>, /// Configuration to be provided to the agent. - /// This parameter can be provided multiple times in the form --config ${DOT_SEPERATED_CONFIG_PATH}=${CONFIG_VALUE}. + /// This parameter can be provided multiple times in the form --config ${DOT_SEPARATED_CONFIG_PATH}=${CONFIG_VALUE}. /// Only configuration declared by the agent can be provided. If a given config path is not provided, the default from the manifest /// (agents.*.config) is used. If neither value nor default is provided and the config is non-optional, creation /// of the agent will fail. @@ -1080,9 +1081,9 @@ pub mod worker { #[command(flatten)] agent_id: AgentIdArgs, /// Agent function name to invoke - function_name: WorkerFunctionName, + function_name: AgentFunctionName, /// Agent function arguments specified using the agent's language's syntax - arguments: Vec, + arguments: Vec, /// Only trigger invocation and do not wait for it #[clap(long, short)] trigger: bool, @@ -1114,7 +1115,7 @@ pub mod worker { List { /// Optional filter for a specific agent type #[arg(conflicts_with = "component_name")] - agent_type_name: Option, + agent_type_name: Option, /// Optional filter for a specific component #[arg(long, conflicts_with = "agent_type_name")] @@ -1133,8 +1134,8 @@ pub mod worker { /// The cursor has the format 'layer/position' where both layer and position are numbers. #[arg(long, short, value_parser = parse_cursor)] scan_cursor: Option, - /// The maximum the number of returned agents, returns all values is not specified. - /// When multiple component is selected, then the limit it is applied separately + /// The maximum number of returned agents; returns all values if not specified. + /// When multiple components are selected, the limit is applied separately. #[arg(long, short)] max_count: Option, /// When set to true it queries for most up-to-date status for each agent, default is false @@ -1156,8 +1157,8 @@ pub mod worker { /// Like stream, but for helping Bridge SDK-based REPLs #[clap(hide = true)] ReplStream { - /// AgentTypeName - agent_type_name: String, + /// Agent type name + agent_type_name: AgentTypeName, /// Agent parameters in UntypedDataValue JSON format parameters: String, /// Idempotency key, used for filtering @@ -1228,7 +1229,7 @@ pub mod worker { /// Idempotency key of the invocation to be cancelled idempotency_key: IdempotencyKey, }, - /// List files in a worker's directory + /// List files in an agent's directory Files { #[command(flatten)] agent_name: AgentIdArgs, @@ -1236,7 +1237,7 @@ pub mod worker { #[arg(default_value = "/")] path: String, }, - /// Get contents of a file in a worker + /// Get contents of a file in an agent FileContents { #[command(flatten)] agent_name: AgentIdArgs, @@ -1397,146 +1398,6 @@ pub mod api { } } - pub mod resource_definition { - use crate::model::EnforcementActionArg; - use clap::Subcommand; - use golem_common::model::quota::ResourceDefinitionId; - - #[derive(Debug, Subcommand)] - pub enum ResourceDefinitionSubcommand { - /// Create a quota resource definition in the environment - Create { - /// Name of the resource (unique within the environment) - name: String, - /// Resource limit as JSON: one of - /// {"type":"rate","value":N,"period":"second|minute|hour|day|month|year","max":N} - /// {"type":"capacity","value":N} - /// {"type":"concurrency","value":N} - #[arg(long)] - limit: String, - /// Enforcement action when the limit is exceeded: throttle | reject | terminate - #[arg(long, default_value_t = EnforcementActionArg::Throttle)] - enforcement_action: EnforcementActionArg, - /// Singular unit label (e.g. "token") - #[arg(long, default_value = "unit")] - unit: String, - /// Plural unit label (e.g. "tokens") - #[arg(long, default_value = "units")] - units: String, - }, - - /// Update an existing quota resource definition - Update { - /// Name of the resource definition - #[arg(required_unless_present = "id", conflicts_with = "id")] - name: Option, - /// ID of the resource definition (alternative to name) - #[arg(long, required_unless_present = "name", conflicts_with = "name")] - id: Option, - /// New resource limit as JSON (optional) - #[arg(long)] - limit: Option, - /// New enforcement action (optional): throttle | reject | terminate - #[arg(long)] - enforcement_action: Option, - /// New singular unit label (optional) - #[arg(long)] - unit: Option, - /// New plural unit label (optional) - #[arg(long)] - units: Option, - }, - - /// Delete a quota resource definition - Delete { - /// Name of the resource definition - #[arg(required_unless_present = "id", conflicts_with = "id")] - name: Option, - /// ID of the resource definition (alternative to name) - #[arg(long, required_unless_present = "name", conflicts_with = "name")] - id: Option, - }, - - /// Get a quota resource definition by name or ID - Get { - /// Name of the resource definition - #[arg(required_unless_present = "id", conflicts_with = "id")] - name: Option, - /// ID of the resource definition (alternative to name) - #[arg(long, required_unless_present = "name", conflicts_with = "name")] - id: Option, - }, - - /// List quota resource definitions in the environment - List, - } - } - - pub mod retry_policy { - use clap::Subcommand; - use golem_common::model::retry_policy::RetryPolicyId; - - #[derive(Debug, Subcommand)] - pub enum RetryPolicySubcommand { - /// Create a retry policy in the environment - Create { - /// Name of the retry policy - name: String, - /// Priority (higher = checked first) - #[arg(long)] - priority: u32, - /// Predicate as JSON or YAML - #[arg(long)] - predicate: String, - /// Policy as JSON or YAML - #[arg(long)] - policy: String, - }, - - /// List retry policies in the environment - List, - - /// Get a retry policy by name or ID - Get { - /// Name of the retry policy - #[arg(required_unless_present = "id", conflicts_with = "id")] - name: Option, - /// ID of the retry policy (alternative to name) - #[arg(long, required_unless_present = "name", conflicts_with = "name")] - id: Option, - }, - - /// Update a retry policy - Update { - /// Name of the retry policy - #[arg(required_unless_present = "id", conflicts_with = "id")] - name: Option, - /// ID of the retry policy (alternative to name) - #[arg(long, required_unless_present = "name", conflicts_with = "name")] - id: Option, - /// New priority (optional) - #[arg(long)] - priority: Option, - /// New predicate as JSON or YAML (optional) - #[arg(long)] - predicate: Option, - /// New policy as JSON or YAML (optional) - #[arg(long)] - policy: Option, - }, - - /// Delete a retry policy - Delete { - /// Name of the retry policy - #[arg(required_unless_present = "id", conflicts_with = "id")] - name: Option, - /// ID of the retry policy (alternative to name) - #[arg(long, required_unless_present = "name", conflicts_with = "name")] - id: Option, - }, - } - } - pub mod security_scheme { use clap::Subcommand; use golem_common::model::security_scheme::{ProviderKind, SecuritySchemeName}; @@ -1635,6 +1496,146 @@ pub mod api { } } +pub mod resource_definition { + use crate::model::EnforcementActionArg; + use clap::Subcommand; + use golem_common::model::quota::ResourceDefinitionId; + + #[derive(Debug, Subcommand)] + pub enum ResourceDefinitionSubcommand { + /// Create a quota resource definition in the environment + Create { + /// Name of the resource (unique within the environment) + name: String, + /// Resource limit as JSON: one of + /// {"type":"rate","value":N,"period":"second|minute|hour|day|month|year","max":N} + /// {"type":"capacity","value":N} + /// {"type":"concurrency","value":N} + #[arg(long)] + limit: String, + /// Enforcement action when the limit is exceeded: throttle | reject | terminate + #[arg(long, default_value_t = EnforcementActionArg::Throttle)] + enforcement_action: EnforcementActionArg, + /// Singular unit label (e.g. "token") + #[arg(long, default_value = "unit")] + unit: String, + /// Plural unit label (e.g. "tokens") + #[arg(long, default_value = "units")] + units: String, + }, + + /// Update an existing quota resource definition + Update { + /// Name of the resource definition + #[arg(required_unless_present = "id", conflicts_with = "id")] + name: Option, + /// ID of the resource definition (alternative to name) + #[arg(long, required_unless_present = "name", conflicts_with = "name")] + id: Option, + /// New resource limit as JSON (optional) + #[arg(long)] + limit: Option, + /// New enforcement action (optional): throttle | reject | terminate + #[arg(long)] + enforcement_action: Option, + /// New singular unit label (optional) + #[arg(long)] + unit: Option, + /// New plural unit label (optional) + #[arg(long)] + units: Option, + }, + + /// Delete a quota resource definition + Delete { + /// Name of the resource definition + #[arg(required_unless_present = "id", conflicts_with = "id")] + name: Option, + /// ID of the resource definition (alternative to name) + #[arg(long, required_unless_present = "name", conflicts_with = "name")] + id: Option, + }, + + /// Get a quota resource definition by name or ID + Get { + /// Name of the resource definition + #[arg(required_unless_present = "id", conflicts_with = "id")] + name: Option, + /// ID of the resource definition (alternative to name) + #[arg(long, required_unless_present = "name", conflicts_with = "name")] + id: Option, + }, + + /// List quota resource definitions in the environment + List, + } +} + +pub mod retry_policy { + use clap::Subcommand; + use golem_common::model::retry_policy::RetryPolicyId; + + #[derive(Debug, Subcommand)] + pub enum RetryPolicySubcommand { + /// Create a retry policy in the environment + Create { + /// Name of the retry policy + name: String, + /// Priority (higher = checked first) + #[arg(long)] + priority: u32, + /// Predicate as JSON or YAML + #[arg(long)] + predicate: String, + /// Policy as JSON or YAML + #[arg(long)] + policy: String, + }, + + /// List retry policies in the environment + List, + + /// Get a retry policy by name or ID + Get { + /// Name of the retry policy + #[arg(required_unless_present = "id", conflicts_with = "id")] + name: Option, + /// ID of the retry policy (alternative to name) + #[arg(long, required_unless_present = "name", conflicts_with = "name")] + id: Option, + }, + + /// Update a retry policy + Update { + /// Name of the retry policy + #[arg(required_unless_present = "id", conflicts_with = "id")] + name: Option, + /// ID of the retry policy (alternative to name) + #[arg(long, required_unless_present = "name", conflicts_with = "name")] + id: Option, + /// New priority (optional) + #[arg(long)] + priority: Option, + /// New predicate as JSON or YAML (optional) + #[arg(long)] + predicate: Option, + /// New policy as JSON or YAML (optional) + #[arg(long)] + policy: Option, + }, + + /// Delete a retry policy + Delete { + /// Name of the retry policy + #[arg(required_unless_present = "id", conflicts_with = "id")] + name: Option, + /// ID of the retry policy (alternative to name) + #[arg(long, required_unless_present = "name", conflicts_with = "name")] + id: Option, + }, + } +} + pub mod plugin { use crate::model::PathBufOrStdin; use clap::Subcommand; @@ -1642,11 +1643,11 @@ pub mod plugin { #[derive(Debug, Subcommand)] pub enum PluginSubcommand { - /// List account components + /// List account plugins List, - /// Get + /// Get plugin details Get { - /// PluginID + /// Plugin ID plugin_id: Uuid, // TODO: atomic: missing method for looking up by name }, /// Register a new plugin for the account @@ -1656,7 +1657,7 @@ pub mod plugin { }, /// Unregister a plugin Unregister { - /// PluginID + /// Plugin ID plugin_id: Uuid, // TODO: atomic: missing method for deleting by name }, } @@ -1918,15 +1919,13 @@ pub fn help_target_to_command(target: ShowClapHelpTarget) -> Command { #[cfg(test)] mod test { - use crate::command::agent_type::AgentTypeSubcommand; - use crate::command::api::agent_secret::AgentSecretSubcommand; + use crate::command::{ - GolemCliCommand, GolemCliSubcommand, builtin_exec_subcommands, - help_target_to_subcommand_names, + GolemCliCommand, builtin_exec_subcommands, help_target_to_subcommand_names, }; use crate::error::ShowClapHelpTarget; use clap::builder::StyledStr; - use clap::{Command, CommandFactory, Parser}; + use clap::{Command, CommandFactory}; use itertools::Itertools; use std::collections::{BTreeMap, BTreeSet}; use strum::IntoEnumIterator; @@ -1937,45 +1936,6 @@ mod test { GolemCliCommand::command().debug_assert(); } - #[test] - fn agent_secret_list_accepts_ids_flag() { - let command = GolemCliCommand::try_parse_from(["golem", "agent-secret", "list", "--ids"]) - .expect("command should parse"); - - let GolemCliSubcommand::AgentSecret { subcommand } = command.subcommand else { - panic!("expected agent-secret subcommand"); - }; - - assert!(matches!( - subcommand, - AgentSecretSubcommand::List { ids: true } - )); - } - - #[test] - fn agent_type_list_parses() { - let command = GolemCliCommand::try_parse_from(["golem", "agent-type", "list"]) - .expect("command should parse"); - - let GolemCliSubcommand::AgentType { subcommand } = command.subcommand else { - panic!("expected agent-type subcommand"); - }; - - assert!(matches!(subcommand, AgentTypeSubcommand::List)); - } - - #[test] - fn agent_type_get_parses() { - let command = GolemCliCommand::try_parse_from(["golem", "agent-type", "get", "CounterAgent"]) - .expect("command should parse"); - - let GolemCliSubcommand::AgentType { subcommand } = command.subcommand else { - panic!("expected agent-type subcommand"); - }; - - assert!(matches!(subcommand, AgentTypeSubcommand::Get { .. })); - } - #[test] fn all_commands_and_args_has_doc() { fn collect_docs( diff --git a/cli/golem-cli/src/command_handler/app/mod.rs b/cli/golem-cli/src/command_handler/app/mod.rs index fbe8c305a9..a81a707766 100644 --- a/cli/golem-cli/src/command_handler/app/mod.rs +++ b/cli/golem-cli/src/command_handler/app/mod.rs @@ -37,8 +37,8 @@ use crate::log::{ log_finished_ok, log_finished_up_to_date, log_skipping_up_to_date, log_warn, log_warn_action, logged_failed_to, logged_finished_or_failed_to, logln, }; -use crate::model::agent::view::AgentTypeView; use crate::model::GuestLanguage; +use crate::model::agent::view::AgentTypeView; use crate::model::app::{ AppBuildStep, ApplicationComponentSelectMode, BuildConfig, CleanMode, DynamicHelpSections, }; diff --git a/cli/golem-cli/src/command_handler/partial_match.rs b/cli/golem-cli/src/command_handler/partial_match.rs index 34e3fe81f5..70c6e172a5 100644 --- a/cli/golem-cli/src/command_handler/partial_match.rs +++ b/cli/golem-cli/src/command_handler/partial_match.rs @@ -25,7 +25,7 @@ use crate::model::app::{ApplicationComponentSelectMode, DynamicHelpSections}; use crate::model::component::ComponentNameMatchKind; use crate::model::format::Format; use crate::model::text::fmt::{DecoratedIndent, log_text_view}; -use crate::model::text::help::{AvailableFunctionNamesHelp, EnvironmentNameHelp, WorkerNameHelp}; +use crate::model::text::help::{AgentNameHelp, AvailableFunctionNamesHelp, EnvironmentNameHelp}; use colored::Colorize; use indoc::indoc; use std::sync::Arc; @@ -186,9 +186,9 @@ impl ErrorHandler { } Ok(()) } - GolemCliCommandPartialMatch::WorkerInvokeMissingWorkerName => { + GolemCliCommandPartialMatch::AgentInvokeMissingAgentName => { logln(""); - log_text_view(&WorkerNameHelp); + log_text_view(&AgentNameHelp); logln(""); self.ctx.silence_app_context_init().await; diff --git a/cli/golem-cli/src/command_handler/resource_definition.rs b/cli/golem-cli/src/command_handler/resource_definition.rs index 0a16301d5f..e4fb7768e2 100644 --- a/cli/golem-cli/src/command_handler/resource_definition.rs +++ b/cli/golem-cli/src/command_handler/resource_definition.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::command::api::resource_definition::ResourceDefinitionSubcommand; +use crate::command::resource_definition::ResourceDefinitionSubcommand; use crate::command_handler::Handlers; use crate::context::Context; use crate::error::NonSuccessfulExit; diff --git a/cli/golem-cli/src/command_handler/retry_policy.rs b/cli/golem-cli/src/command_handler/retry_policy.rs index 904b7e2359..327273f06e 100644 --- a/cli/golem-cli/src/command_handler/retry_policy.rs +++ b/cli/golem-cli/src/command_handler/retry_policy.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::command::api::retry_policy::RetryPolicySubcommand; +use crate::command::retry_policy::RetryPolicySubcommand; use crate::command_handler::Handlers; use crate::context::Context; use crate::error::NonSuccessfulExit; diff --git a/cli/golem-cli/src/command_handler/worker/mod.rs b/cli/golem-cli/src/command_handler/worker/mod.rs index b8a1164b60..9947180bbe 100644 --- a/cli/golem-cli/src/command_handler/worker/mod.rs +++ b/cli/golem-cli/src/command_handler/worker/mod.rs @@ -16,7 +16,7 @@ mod stream; mod stream_output; use crate::command::shared_args::{ - AgentIdArgs, PostDeployArgs, StreamArgs, WorkerFunctionArgument, WorkerFunctionName, + AgentFunctionArgument, AgentFunctionName, AgentIdArgs, PostDeployArgs, StreamArgs, }; use crate::command::worker::AgentSubcommand; use crate::command_handler::Handlers; @@ -34,7 +34,7 @@ use crate::model::deploy::{TryUpdateAllWorkersResult, WorkerUpdateAttempt}; use crate::model::invoke_result_view::InvokeResultView; use crate::model::text::fmt::{log_fuzzy_match, log_text_view}; use crate::model::text::help::{ - AvailableAgentConstructorsHelp, AvailableFunctionNamesHelp, WorkerNameHelp, + AgentNameHelp, AvailableAgentConstructorsHelp, AvailableFunctionNamesHelp, }; use crate::model::text::worker::{ FileNodeView, WorkerCreateView, WorkerFilesView, WorkerGetView, format_agent_name_match, @@ -312,8 +312,8 @@ impl WorkerCommandHandler { async fn cmd_invoke( &self, agent_name: AgentIdArgs, - function_name: &WorkerFunctionName, - arguments: Vec, + function_name: &AgentFunctionName, + arguments: Vec, trigger: bool, idempotency_key: Option, no_stream: bool, @@ -579,7 +579,7 @@ impl WorkerCommandHandler { async fn cmd_repl_stream( &self, - agent_type_name: String, + agent_type_name: AgentTypeName, parameters: String, idempotency_key: IdempotencyKey, phantom_id: Option, @@ -599,10 +599,10 @@ impl WorkerCommandHandler { let Some(agent_type) = self .ctx .app_handler() - .get_agent_type_by_name(&environment, &agent_type_name) + .get_agent_type_by_name(&environment, agent_type_name.0.as_str()) .await? else { - bail!("Agent type not found: {}", agent_type_name); + bail!("Agent type not found: {}", agent_type_name.0); }; let typed_parameters = DataValue::try_from_untyped_json( @@ -813,7 +813,7 @@ impl WorkerCommandHandler { async fn cmd_list( &self, - agent_type_name: Option, + agent_type_name: Option, component_name: Option, filters: Vec, scan_cursor: Option, @@ -898,7 +898,7 @@ impl WorkerCommandHandler { async fn resolve_list_components( &self, - agent_type_name: Option, + agent_type_name: Option, component_name: Option, filters: Vec, ) -> anyhow::Result<(Vec, Vec)> { @@ -912,16 +912,16 @@ impl WorkerCommandHandler { .environment_handler() .resolve_environment(EnvironmentResolveMode::Any) .await?; - debug!("Finding agent type {}", agent_type_name); + debug!("Finding agent type {}", agent_type_name.0); let Some(agent_type) = self .ctx .app_handler() - .get_agent_type_by_name(&environment, &agent_type_name) + .get_agent_type_by_name(&environment, agent_type_name.0.as_str()) .await? else { log_error(format!( "Agent type {} not found", - agent_type_name.log_color_highlight() + agent_type_name.0.log_color_highlight() )); bail!(NonSuccessfulExit) }; @@ -2232,7 +2232,7 @@ impl WorkerCommandHandler { agent_name.log_color_error_highlight() )); logln(""); - log_text_view(&WorkerNameHelp); + log_text_view(&AgentNameHelp); bail!(NonSuccessfulExit); } }; @@ -2253,7 +2253,7 @@ impl WorkerCommandHandler { "Deploy the component that defines this agent type or specify environment/application/account prefixes.", ); logln(""); - log_text_view(&WorkerNameHelp); + log_text_view(&AgentNameHelp); bail!(NonSuccessfulExit); }; @@ -2303,7 +2303,7 @@ impl WorkerCommandHandler { name = name.log_color_highlight() )); logln(""); - log_text_view(&WorkerNameHelp); + log_text_view(&AgentNameHelp); bail!(NonSuccessfulExit); } Ok(value) @@ -2324,7 +2324,7 @@ impl WorkerCommandHandler { err = err.log_color_error_highlight() )); logln(""); - log_text_view(&WorkerNameHelp); + log_text_view(&AgentNameHelp); bail!(NonSuccessfulExit); } } @@ -2391,7 +2391,7 @@ impl WorkerCommandHandler { agent_name.0.log_color_error_highlight() )); logln(""); - log_text_view(&WorkerNameHelp); + log_text_view(&AgentNameHelp); bail!(NonSuccessfulExit); } } diff --git a/cli/golem-cli/src/model/text/help.rs b/cli/golem-cli/src/model/text/help.rs index 7b1991d059..144fa57576 100644 --- a/cli/golem-cli/src/model/text/help.rs +++ b/cli/golem-cli/src/model/text/help.rs @@ -26,9 +26,9 @@ use golem_wasm::analysis::AnalysedType; use indoc::indoc; use std::path::PathBuf; -pub struct WorkerNameHelp; +pub struct AgentNameHelp; -impl MessageWithFields for WorkerNameHelp { +impl MessageWithFields for AgentNameHelp { fn message(&self) -> String { "Accepted agent name formats:" .log_color_help_group()