Class: Ace::Core::Atoms::ConfigSummary

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/core/atoms/config_summary.rb

Overview

ConfigSummary displays effective configuration state to stderr.

Only shows values that differ from defaults, filtering sensitive keys. Output format: "Config: key=value key2=value2" (space-separated)

Sensitive Key Filtering

Keys ending with sensitive patterns are filtered out:

  • token, password, secret, credential, key, api_key

Keys containing these patterns but NOT ending with them are shown:

  • max_tokens (contains "tokens" but doesn't end with it) ✓ shown
  • keyboard_layout (contains "key" but doesn't end with it) ✓ shown
  • auth_token (ends with "token") ✗ filtered
  • api_key (ends with "key") ✗ filtered

Usage

ConfigSummary.display(
command: "review",
config: Gem.config,            # Effective config
defaults: Gem.default_config,   # Defaults for diffing
options: { verbose: true },     # Thor options hash
quiet: false,
summary_keys: %w[model preset] # Optional allowlist
)
# Output to stderr: "Config: model=gflash preset=pr"

Constant Summary collapse

SENSITIVE_REGEX =

Match keys ENDING with sensitive words (not containing them)

/(_|^)(token|password|secret|credential|key|api_key)$/i

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(command, config, defaults, options, summary_keys) ⇒ ConfigSummary

Returns a new instance of ConfigSummary.



142
143
144
145
146
147
148
# File 'lib/ace/core/atoms/config_summary.rb', line 142

def initialize(command, config, defaults, options, summary_keys)
  @command = command
  @config = flatten_hash(config || {})
  @defaults = flatten_hash(defaults || {})
  @options = options || {}
  @summary_keys = summary_keys&.map(&:to_s)
end

Class Method Details

.display(command:, config: {}, defaults: {}, options: {}, quiet: false, summary_keys: nil) ⇒ nil

Display configuration summary to stderr

Examples:

Basic usage

ConfigSummary.display(
  command: "review",
  config: { model: "gflash", format: "markdown" },
  defaults: { "model" => "glite", "format" => "markdown" },
  options: { verbose: true }
)
# Outputs: "Config: model=gflash verbose=true"

With quiet mode

ConfigSummary.display(
  command: "review",
  config: { model: "gflash" },
  defaults: {},
  options: {},
  quiet: true
)
# No output

With allowlist

ConfigSummary.display(
  command: "review",
  config: { model: "gflash", format: "markdown" },
  defaults: {},
  options: { verbose: true },
  summary_keys: %w[model]
)
# Outputs: "Config: model=gflash"
# (format and verbose not in allowlist)

Parameters:

  • command (String)

    Command name for context

  • config (Hash) (defaults to: {})

    Effective configuration (merged result)

  • defaults (Hash) (defaults to: {})

    Default configuration to diff against

  • options (Hash) (defaults to: {})

    CLI options (Thor options hash)

  • quiet (Boolean) (defaults to: false)

    Suppress output if true

  • summary_keys (Array<String>, nil) (defaults to: nil)

    Allowlist of keys to include (nil = all non-sensitive)

Returns:

  • (nil)


82
83
84
85
86
87
88
89
90
# File 'lib/ace/core/atoms/config_summary.rb', line 82

def self.display(command:, config: {}, defaults: {}, options: {}, quiet: false, summary_keys: nil)
  return if quiet

  # Only display config when verbose mode is explicitly enabled
  return unless options[:verbose]

  summary = new(command, config, defaults, options, summary_keys).build
  warn "Config: #{summary}" unless summary.empty?
end

.display_if_needed(command:, config: {}, defaults: {}, options: {}, quiet: false, summary_keys: nil, args: ARGV) ⇒ nil

Display configuration summary only if help was NOT requested.

This is the recommended method for commands that need to show config but want to avoid polluting --help output with configuration details.

Examples:

Usage in command

def execute
  # Check for help BEFORE displaying config
  return show_help if help_requested?(options, args)

  # Now safe to display config
  ConfigSummary.display_if_needed(
    command: "review",
    config: Gem.config,
    defaults: Gem.default_config,
    options: options
  )
end

Parameters:

  • command (String)

    Command name for context

  • config (Hash) (defaults to: {})

    Effective configuration (merged result)

  • defaults (Hash) (defaults to: {})

    Default configuration to diff against

  • options (Hash) (defaults to: {})

    CLI options (Thor options hash)

  • quiet (Boolean) (defaults to: false)

    Suppress output if true

  • summary_keys (Array<String>, nil) (defaults to: nil)

    Allowlist of keys to include (nil = all non-sensitive)

Returns:

  • (nil)


119
120
121
122
123
124
# File 'lib/ace/core/atoms/config_summary.rb', line 119

def self.display_if_needed(command:, config: {}, defaults: {}, options: {}, quiet: false, summary_keys: nil, args: ARGV)
  return if quiet
  return if help_requested?(options, args)

  display(command: command, config: config, defaults: defaults, options: options, summary_keys: summary_keys)
end

.help_requested?(options = {}, args = ARGV) ⇒ Boolean

Note:

The args parameter defaults to ARGV for CLI usage convenience. In test or non-CLI contexts, pass an explicit array to avoid global state.

Check if help was requested via options or arguments.

Parameters:

  • options (Hash) (defaults to: {})

    CLI options hash (from Thor)

  • args (Array<String>) (defaults to: ARGV)

    Command arguments (defaults to ARGV for CLI context)

Returns:

  • (Boolean)

    true if help was requested



135
136
137
138
139
140
# File 'lib/ace/core/atoms/config_summary.rb', line 135

def self.help_requested?(options = {}, args = ARGV)
  options[:help] ||
    options[:h] ||
    args.include?("--help") ||
    args.include?("-h")
end

Instance Method Details

#buildString

Build the configuration summary string

Returns:

  • (String)

    Space-separated key=value pairs



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/ace/core/atoms/config_summary.rb', line 153

def build
  pairs = []

  # 1. Add CLI options that were explicitly set (non-nil, non-false)
  @options.each do |key, value|
    next if value.nil? || value == false
    next if sensitive_key?(key.to_s)
    next if @summary_keys && !@summary_keys.include?(key.to_s)
    pairs << format_pair(key, value)
  end

  # 2. Add config values that differ from defaults (if not already in options)
  @config.each do |key, value|
    # Skip if already shown from options (check both symbol and string)
    next if @options.key?(key.to_sym) || @options.key?(key.to_s)
    next if @defaults[key] == value
    next if sensitive_key?(key)
    next if @summary_keys && !@summary_keys.include?(key)
    pairs << format_pair(key, value)
  end

  pairs.sort.join(" ")
end