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