diff --git a/lib/classifier/cli.rb b/lib/classifier/cli.rb index 6c673942..001e4163 100644 --- a/lib/classifier/cli.rb +++ b/lib/classifier/cli.rb @@ -95,6 +95,13 @@ def parse_options @options[:type] = type end + opts.on( + '--search TEXT', + 'Search remote models by name/description, and local models by name only. Use quotes for multiword search' + ) do |text| + @options[:search] = text + end + opts.on('-r', '--remote MODEL', 'Use remote model: name or @user/repo:name') do |model| @options[:remote] = model end @@ -376,12 +383,20 @@ def list_remote_models return if @exit_code != 0 - if index['models'].empty? + models = index['models'] + + if @options[:search] + models = models.filter do |name, info| + [name, info['description']].any?(/#{Regexp.escape(@options[:search])}/i) + end + end + + if models.empty? @output << 'No models found in registry' return end - index['models'].each do |name, info| + models.each do |name, info| type = info['type'] || 'unknown' size = info['size'] || 'unknown' desc = info['description'] || '' @@ -413,6 +428,12 @@ def list_local_models models = default_models + custom_models #: Array[{name: String, registry: String?, path: String}] + if @options[:search] + models = models.filter do |model| + model[:name] =~ /#{Regexp.escape(@options[:search])}/i + end + end + if models.empty? @output << 'No local models found' return diff --git a/test/cli/registry_commands_test.rb b/test/cli/registry_commands_test.rb index 613d8c3d..a658217e 100644 --- a/test/cli/registry_commands_test.rb +++ b/test/cli/registry_commands_test.rb @@ -151,6 +151,64 @@ def test_models_local_shows_no_models_when_cache_dir_missing assert_match(/no local models found/i, result[:output]) end + def test_models_remote_search_by_name + stub_request(:get, 'https://raw.githubusercontent.com/cardmagic/classifier-models/main/models.json') + .to_return(status: 200, body: @models_json) + + result = run_cli('models', '--search', 'spam-filter') + + assert_equal 0, result[:exit_code] + assert_match(/spam-filter/, result[:output]) + refute_match(/sentiment/, result[:output]) + end + + def test_models_remote_search_by_description + stub_request(:get, 'https://raw.githubusercontent.com/cardmagic/classifier-models/main/models.json') + .to_return(status: 200, body: @models_json) + + result = run_cli('models', '--search', 'Spam Detection') + + assert_equal 0, result[:exit_code] + assert_match(/spam-filter/, result[:output]) + refute_match(/sentiment/, result[:output]) + end + + def test_models_remote_search_no_found + stub_request(:get, 'https://raw.githubusercontent.com/cardmagic/classifier-models/main/models.json') + .to_return(status: 200, body: @models_json) + + result = run_cli('models', '--search', '[a-z]+') + + assert_equal 0, result[:exit_code] + assert_match(/No models found in registry/, result[:output]) + end + + def test_models_local_search_by_name + # Create some cached models + models_dir = File.join(@cache_dir, 'models') + FileUtils.mkdir_p(models_dir) + File.write(File.join(models_dir, 'spam-filter.json'), @model_json) + File.write(File.join(models_dir, 'sentiment.json'), @model_json) + + result = run_cli('models', '--local', '--search', 'spam-filter') + + assert_equal 0, result[:exit_code] + assert_match(/spam-filter/, result[:output]) + refute_match(/sentiment/, result[:output]) + end + + def test_models_local_search_no_found + # Create some cached models + models_dir = File.join(@cache_dir, 'models') + FileUtils.mkdir_p(models_dir) + File.write(File.join(models_dir, 'spam-filter.json'), @model_json) + + result = run_cli('models', '--local', '--search', '[a-z]+') + + assert_equal 0, result[:exit_code] + assert_match(/No local models found/, result[:output]) + end + # # Pull Command #