Class: AgentCliRuntime::Profile
- Inherits:
-
Object
- Object
- AgentCliRuntime::Profile
- Defined in:
- lib/agent_cli_runtime/profile.rb
Constant Summary collapse
- PROMPT_STYLES =
%i[positional headless_flag_value stdin].freeze
- WORKSPACE_WRITE_PERMISSION_MODE =
"workspace-write".freeze
- READ_ONLY_PERMISSION_MODE =
"read-only".freeze
- CAPTURE_TIMEOUT_SECONDS =
10- CAPTURE_POLL_SECONDS =
0.01- CAPTURE_TERM_GRACE_SECONDS =
0.2- CAPTURE_REAP_GRACE_SECONDS =
0.2
Instance Attribute Summary collapse
-
#add_dir_flag ⇒ Object
readonly
Returns the value of attribute add_dir_flag.
-
#bin_default ⇒ Object
readonly
Returns the value of attribute bin_default.
-
#budget_flag ⇒ Object
readonly
Returns the value of attribute budget_flag.
-
#cli_capabilities ⇒ Object
readonly
Returns the value of attribute cli_capabilities.
-
#configuration_environment_key ⇒ Object
readonly
Returns the value of attribute configuration_environment_key.
-
#credential_environment_keys ⇒ Object
readonly
Returns the value of attribute credential_environment_keys.
-
#declared_capability_support ⇒ Object
readonly
Returns the value of attribute declared_capability_support.
-
#default_configuration_directory ⇒ Object
readonly
Returns the value of attribute default_configuration_directory.
-
#effort_argument_builder ⇒ Object
readonly
Returns the value of attribute effort_argument_builder.
-
#env_bin_override_keys ⇒ Object
readonly
Returns the value of attribute env_bin_override_keys.
-
#headless_flag ⇒ Object
readonly
Returns the value of attribute headless_flag.
-
#launcher_identity ⇒ Object
readonly
Returns the value of attribute launcher_identity.
-
#min_version ⇒ Object
readonly
Returns the value of attribute min_version.
-
#model_argument_builder ⇒ Object
readonly
Returns the value of attribute model_argument_builder.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#output_format_flags ⇒ Object
readonly
Returns the value of attribute output_format_flags.
-
#permission_skip_flag ⇒ Object
readonly
Returns the value of attribute permission_skip_flag.
-
#prompt_style ⇒ Object
readonly
Returns the value of attribute prompt_style.
-
#read_only_flags ⇒ Object
readonly
Returns the value of attribute read_only_flags.
-
#tool_scope_flags ⇒ Object
readonly
Returns the value of attribute tool_scope_flags.
-
#version_flag ⇒ Object
readonly
Returns the value of attribute version_flag.
-
#workspace_write_flags ⇒ Object
readonly
Returns the value of attribute workspace_write_flags.
Instance Method Summary collapse
- #auth_configuration(home: nil, env: ENV) ⇒ Object
- #bin(env: ENV) ⇒ Object
- #binary_installed?(env: ENV) ⇒ Boolean
- #check_version!(env: ENV) ⇒ Object
- #configuration_directory(home: nil, env: ENV) ⇒ Object
- #extract_usage_event(event) ⇒ Object
- #identity_arguments(model:, effort:, pin_model: true) ⇒ Object
-
#initialize(name:, bin_default:, headless_flag:, version_flag:, env_bin_override_keys: [], permission_skip_flag: nil, workspace_write_flags: [], read_only_flags: [], add_dir_flag: nil, tool_scope_flags: {}, budget_flag: nil, output_format_flags: [], min_version: nil, prompt_style: :positional, model_argument_builder: nil, effort_argument_builder: nil, launcher_identity: nil, usage_extractor: nil, auth_configuration_probe: nil, cli_capabilities: {}, raw_cli_arguments_supported: false, credential_environment_keys: [], configuration_environment_key: nil, default_configuration_directory: nil) ⇒ Profile
constructor
A new instance of Profile.
- #permission_flags(permission_mode = nil) ⇒ Object
- #raw_cli_arguments_supported? ⇒ Boolean
- #require_cli_capability!(capability) ⇒ Object
Constructor Details
#initialize(name:, bin_default:, headless_flag:, version_flag:, env_bin_override_keys: [], permission_skip_flag: nil, workspace_write_flags: [], read_only_flags: [], add_dir_flag: nil, tool_scope_flags: {}, budget_flag: nil, output_format_flags: [], min_version: nil, prompt_style: :positional, model_argument_builder: nil, effort_argument_builder: nil, launcher_identity: nil, usage_extractor: nil, auth_configuration_probe: nil, cli_capabilities: {}, raw_cli_arguments_supported: false, credential_environment_keys: [], configuration_environment_key: nil, default_configuration_directory: nil) ⇒ Profile
Returns a new instance of Profile.
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/agent_cli_runtime/profile.rb', line 32 def initialize(name:, bin_default:, headless_flag:, version_flag:, env_bin_override_keys: [], permission_skip_flag: nil, workspace_write_flags: [], read_only_flags: [], add_dir_flag: nil, tool_scope_flags: {}, budget_flag: nil, output_format_flags: [], min_version: nil, prompt_style: :positional, model_argument_builder: nil, effort_argument_builder: nil, launcher_identity: nil, usage_extractor: nil, auth_configuration_probe: nil, cli_capabilities: {}, raw_cli_arguments_supported: false, credential_environment_keys: [], configuration_environment_key: nil, default_configuration_directory: nil) normalized_prompt_style = prompt_style.to_sym unless PROMPT_STYLES.include?(normalized_prompt_style) raise ArgumentError, "unknown prompt_style #{prompt_style.inspect}; valid: #{PROMPT_STYLES.inspect}" end @name = name.to_sym @bin_default = immutable_string(bin_default) @env_bin_override_keys = immutable_strings(env_bin_override_keys) @headless_flag = immutable_string(headless_flag) @permission_skip_flag = .nil? ? nil : immutable_string() @workspace_write_flags = immutable_strings(workspace_write_flags) @read_only_flags = immutable_strings(read_only_flags) @add_dir_flag = add_dir_flag.nil? ? nil : immutable_string(add_dir_flag) @tool_scope_flags = normalize_tool_scope_flags(tool_scope_flags) @budget_flag = budget_flag.nil? ? nil : immutable_string(budget_flag) @output_format_flags = immutable_strings(output_format_flags) @version_flag = immutable_string(version_flag) @min_version = min_version.nil? ? nil : immutable_string(min_version) @prompt_style = normalized_prompt_style @model_argument_builder = model_argument_builder @effort_argument_builder = effort_argument_builder @launcher_identity = immutable_string(launcher_identity || "agent-cli-runtime/v1:#{@name}") @usage_extractor = usage_extractor || ->(_event) { nil } @auth_configuration_probe = auth_configuration_probe @cli_capabilities = normalize_cli_capabilities(cli_capabilities) @raw_cli_arguments_supported = raw_cli_arguments_supported == true @credential_environment_keys = immutable_environment_keys( credential_environment_keys ) @configuration_environment_key = optional_environment_key( configuration_environment_key ) @default_configuration_directory = optional_relative_directory( default_configuration_directory ) @declared_capability_support = build_declared_capability_support freeze end |
Instance Attribute Details
#add_dir_flag ⇒ Object (readonly)
Returns the value of attribute add_dir_flag.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def add_dir_flag @add_dir_flag end |
#bin_default ⇒ Object (readonly)
Returns the value of attribute bin_default.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def bin_default @bin_default end |
#budget_flag ⇒ Object (readonly)
Returns the value of attribute budget_flag.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def budget_flag @budget_flag end |
#cli_capabilities ⇒ Object (readonly)
Returns the value of attribute cli_capabilities.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def cli_capabilities @cli_capabilities end |
#configuration_environment_key ⇒ Object (readonly)
Returns the value of attribute configuration_environment_key.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def configuration_environment_key @configuration_environment_key end |
#credential_environment_keys ⇒ Object (readonly)
Returns the value of attribute credential_environment_keys.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def credential_environment_keys @credential_environment_keys end |
#declared_capability_support ⇒ Object (readonly)
Returns the value of attribute declared_capability_support.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def declared_capability_support @declared_capability_support end |
#default_configuration_directory ⇒ Object (readonly)
Returns the value of attribute default_configuration_directory.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def default_configuration_directory @default_configuration_directory end |
#effort_argument_builder ⇒ Object (readonly)
Returns the value of attribute effort_argument_builder.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def effort_argument_builder @effort_argument_builder end |
#env_bin_override_keys ⇒ Object (readonly)
Returns the value of attribute env_bin_override_keys.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def env_bin_override_keys @env_bin_override_keys end |
#headless_flag ⇒ Object (readonly)
Returns the value of attribute headless_flag.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def headless_flag @headless_flag end |
#launcher_identity ⇒ Object (readonly)
Returns the value of attribute launcher_identity.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def launcher_identity @launcher_identity end |
#min_version ⇒ Object (readonly)
Returns the value of attribute min_version.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def min_version @min_version end |
#model_argument_builder ⇒ Object (readonly)
Returns the value of attribute model_argument_builder.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def model_argument_builder @model_argument_builder end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def name @name end |
#output_format_flags ⇒ Object (readonly)
Returns the value of attribute output_format_flags.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def output_format_flags @output_format_flags end |
#permission_skip_flag ⇒ Object (readonly)
Returns the value of attribute permission_skip_flag.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def @permission_skip_flag end |
#prompt_style ⇒ Object (readonly)
Returns the value of attribute prompt_style.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def prompt_style @prompt_style end |
#read_only_flags ⇒ Object (readonly)
Returns the value of attribute read_only_flags.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def read_only_flags @read_only_flags end |
#tool_scope_flags ⇒ Object (readonly)
Returns the value of attribute tool_scope_flags.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def tool_scope_flags @tool_scope_flags end |
#version_flag ⇒ Object (readonly)
Returns the value of attribute version_flag.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def version_flag @version_flag end |
#workspace_write_flags ⇒ Object (readonly)
Returns the value of attribute workspace_write_flags.
22 23 24 |
# File 'lib/agent_cli_runtime/profile.rb', line 22 def workspace_write_flags @workspace_write_flags end |
Instance Method Details
#auth_configuration(home: nil, env: ENV) ⇒ Object
195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/agent_cli_runtime/profile.rb', line 195 def auth_configuration(home: nil, env: ENV) return AuthConfiguration.new(status: :not_checked) unless @auth_configuration_probe result = @auth_configuration_probe.call(home: home, env: env) return result if result.is_a?(AuthConfiguration) raise TypeError, "auth_configuration_probe must return AgentCliRuntime::AuthConfiguration" rescue StandardError => e AuthConfiguration.new( status: :missing, diagnostic: Redactor.diagnostic(e) ) end |
#bin(env: ENV) ⇒ Object
85 86 87 88 89 90 |
# File 'lib/agent_cli_runtime/profile.rb', line 85 def bin(env: ENV) key = @env_bin_override_keys.find do |candidate| !env[candidate].to_s.empty? end key ? env.fetch(key) : @bin_default end |
#binary_installed?(env: ENV) ⇒ Boolean
148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/agent_cli_runtime/profile.rb', line 148 def binary_installed?(env: ENV) executable = bin(env:) return File.file?(executable) && File.executable?(executable) if executable.include?(File::SEPARATOR) env.fetch("PATH", "").split(File::PATH_SEPARATOR).any? do |directory| candidate = File.join(directory, executable) File.file?(candidate) && File.executable?(candidate) end rescue ArgumentError false end |
#check_version!(env: ENV) ⇒ Object
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/agent_cli_runtime/profile.rb', line 160 def check_version!(env: ENV) executable = bin(env:) out, _err, status = bounded_capture3( executable, @version_flag, timeout_sec: CAPTURE_TIMEOUT_SECONDS, env: env ) unless status.success? raise BinaryUnavailable, "#{@name} binary not runnable: #{executable}" end versions = out.scan(VERSION_TOKEN_PATTERN).flatten.uniq if versions.empty? raise VersionError, "could not parse #{@name} #{@version_flag} output" end if versions.length > 1 raise VersionError, "ambiguous #{@name} #{@version_flag} output: " \ "#{versions.join(', ')}" end version = versions.fetch(0) if @min_version && Gem::Version.new(version) < Gem::Version.new(@min_version) raise VersionError, "#{@name} #{version} below minimum #{@min_version}" end version.freeze rescue Errno::ENOENT, Errno::EACCES => e raise BinaryUnavailable, "#{@name} binary not runnable: #{executable} (#{e.class.name.split('::').last})" rescue Timeout::Error raise BinaryUnavailable, "#{@name} version check timed out after #{CAPTURE_TIMEOUT_SECONDS}s: #{executable}" end |
#configuration_directory(home: nil, env: ENV) ⇒ Object
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/agent_cli_runtime/profile.rb', line 216 def configuration_directory(home: nil, env: ENV) if @configuration_environment_key configured = env[@configuration_environment_key].to_s unless configured.empty? unless File.absolute_path?(configured) raise ArgumentError, "#{@configuration_environment_key} must be an absolute directory" end return File.(configured) end end return nil unless @default_configuration_directory base = home || env["HOME"] base = Dir.home if base.to_s.empty? File.(@default_configuration_directory, base) end |
#extract_usage_event(event) ⇒ Object
210 211 212 213 214 |
# File 'lib/agent_cli_runtime/profile.rb', line 210 def extract_usage_event(event) @usage_extractor.call(event) rescue StandardError nil end |
#identity_arguments(model:, effort:, pin_model: true) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/agent_cli_runtime/profile.rb', line 112 def identity_arguments(model:, effort:, pin_model: true) normalized_model = nonempty_value(model, "model") normalized_effort = effort.nil? ? nil : nonempty_value(effort, "effort") native_arguments = [] if pin_model unless @model_argument_builder raise UnsupportedCapability, "agent profile #{@name.inspect} cannot pin a model" end native_arguments.concat(@model_argument_builder.call(normalized_model)) end effective_effort = nil if normalized_effort unless @effort_argument_builder raise UnsupportedCapability, "agent profile #{@name.inspect} cannot set reasoning effort" end native_arguments.concat(@effort_argument_builder.call(normalized_effort)) effective_effort = normalized_effort end IdentityArguments.new( model: normalized_model, requested_effort: normalized_effort, effective_effort: effective_effort, effort_supported: !@effort_argument_builder.nil?, model_pinned: pin_model, native_arguments: validate_arguments(native_arguments) ) end |
#permission_flags(permission_mode = nil) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/agent_cli_runtime/profile.rb', line 92 def ( = nil) if == WORKSPACE_WRITE_PERMISSION_MODE return @workspace_write_flags.dup unless @workspace_write_flags.empty? raise ArgumentError, "agent profile #{@name.inspect} cannot enforce workspace-write sandboxing" end if == READ_ONLY_PERMISSION_MODE return @read_only_flags.dup unless @read_only_flags.empty? raise ArgumentError, "agent profile #{@name.inspect} cannot enforce read-only sandboxing" end return [] unless @permission_skip_flag return [ @permission_skip_flag ] unless @name == :claude && return [ @permission_skip_flag ] if == "bypassPermissions" [ "--permission-mode", .to_s ] end |
#raw_cli_arguments_supported? ⇒ Boolean
144 145 146 |
# File 'lib/agent_cli_runtime/profile.rb', line 144 def raw_cli_arguments_supported? @raw_cli_arguments_supported end |
#require_cli_capability!(capability) ⇒ Object
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/agent_cli_runtime/profile.rb', line 234 def require_cli_capability!(capability) capability_name = capability.to_sym flags = @cli_capabilities[capability_name] unless flags raise UnsupportedCapability, "agent profile #{@name.inspect} does not declare CLI capability " \ "#{capability_name.inspect}" end help = capture_help(flags) missing = flags.grep(/\A-/).reject { |flag| flag_advertised?(help, flag) } unless missing.empty? raise UnsupportedCapability, "#{@name} does not advertise required #{capability_name} capability " \ "(missing #{missing.join(', ')})" end flags.dup end |