Class: RailsAiBridge::Registry::RakePresenter

Inherits:
Object
  • Object
show all
Includes:
Truncatable
Defined in:
lib/rails_ai_bridge/registry/rake_presenter.rb

Overview

Formats registry data for CLI output in rake tasks.

Single responsibility: converts resolver data into human-readable stdout strings for rake tasks. Does not know about MCP, tools, or configuration. Rake tasks delegate all formatting here to stay DRY with each other.

Examples:

presenter = RakePresenter.new(resolver)
puts presenter.skills_table
puts presenter.resolve_skill_output('code-review', requested_pack: 'rails')

Constant Summary collapse

SKILL_NAME_COL =
30
PACK_NAME_COL =
15
DESC_MAX_LENGTH =
50
TABLE_WIDTH =
80
NO_MANIFEST_MESSAGE =
<<~MSG
  No registry manifest found at '%<path>s'.
  Create the file and configure skill packs. See docs/skill-registry-guide.md for details.
MSG

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Truncatable

#sanitize_markdown, #truncate

Constructor Details

#initialize(resolver) ⇒ RakePresenter

Returns a new instance of RakePresenter.

Parameters:

Raises:

  • (ArgumentError)

    if resolver is nil



30
31
32
33
34
# File 'lib/rails_ai_bridge/registry/rake_presenter.rb', line 30

def initialize(resolver)
  raise ArgumentError, 'RakePresenter requires a resolver; got nil — check registry configuration' if resolver.nil?

  @resolver = resolver
end

Class Method Details

.no_manifest_message(path) ⇒ String

Parameters:

  • path (String)

    manifest path that was not found

Returns:

  • (String)


73
74
75
# File 'lib/rails_ai_bridge/registry/rake_presenter.rb', line 73

def self.no_manifest_message(path)
  format(NO_MANIFEST_MESSAGE, path: path)
end

.require_resolver!Registry::Resolver

Builds a resolver or exits with an error message if none is available.

Encapsulates the repeated pattern across rake tasks: build the resolver, warn with the no-manifest message, and exit 1 if it is nil.

Returns:



83
84
85
86
87
88
89
90
# File 'lib/rails_ai_bridge/registry/rake_presenter.rb', line 83

def self.require_resolver!
  resolver = RailsAiBridge::Registry.build_resolver
  return resolver if resolver

  path = RailsAiBridge.configuration.registry.registry_manifest_path
  warn no_manifest_message(path)
  exit 1 # rubocop:disable Rails/Exit
end

Instance Method Details

#resolve_skill_output(name, requested_pack: nil) ⇒ String

Returns multi-line output including content, or an error message.

Parameters:

  • name (String)

    skill name

  • requested_pack (String, nil) (defaults to: nil)

    optional pack the user asked for

Returns:

  • (String)

    multi-line output including content, or an error message



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/rails_ai_bridge/registry/rake_presenter.rb', line 54

def resolve_skill_output(name, requested_pack: nil)
  resolved = @resolver.resolve_skill(name)
  return "Skill '#{name}' not found in any loaded pack.\nRun `rails ai:skills:list` to see available skills.\n" unless resolved

  lines = []
  warning = @resolver.check_deprecated(name)
  lines << "WARNING: #{warning}" if warning

  lines << "INFO: Skill '#{name}' resolved from pack '#{resolved.pack}' (requested pack: '#{requested_pack}')." if requested_pack && resolved.pack != requested_pack

  lines << "# #{resolved.name} (from pack: #{resolved.pack})"
  lines << "# Path: #{resolved.path}"
  lines << ''
  lines << resolved.content
  lines.join("\n")
end

#skills_tableString

Returns skills table for stdout, or an error/empty message.

Returns:

  • (String)

    skills table for stdout, or an error/empty message



37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/rails_ai_bridge/registry/rake_presenter.rb', line 37

def skills_table
  skills = @resolver.list_skills
  return "No skills are loaded. Check your registry manifest configuration.\n" if skills.empty?

  lines = ["Available Skills (#{skills.length})", '']
  lines << "#{'Skill'.ljust(SKILL_NAME_COL)} #{'Pack'.ljust(PACK_NAME_COL)} Description"
  lines << ('-' * TABLE_WIDTH)
  skills.each do |skill|
    desc = truncate(skill.description, DESC_MAX_LENGTH)
    lines << "#{skill.name.ljust(SKILL_NAME_COL)} #{skill.pack.ljust(PACK_NAME_COL)} #{desc}"
  end
  lines.join("\n")
end