exa-ai 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,6 +7,8 @@ require "exa-ai"
7
7
  webset_id = nil
8
8
  api_key = nil
9
9
  output_format = "json"
10
+ limit = nil
11
+ cursor = nil
10
12
 
11
13
  args = ARGV.dup
12
14
  while args.any?
@@ -16,6 +18,10 @@ while args.any?
16
18
  api_key = args.shift
17
19
  when "--output-format"
18
20
  output_format = args.shift
21
+ when "--limit"
22
+ limit = args.shift&.to_i
23
+ when "--cursor"
24
+ cursor = args.shift
19
25
  when "--help", "-h"
20
26
  puts <<~HELP
21
27
  Usage: exa-ai webset-item-list <webset_id> [OPTIONS]
@@ -26,14 +32,17 @@ while args.any?
26
32
  webset_id ID of the webset (required)
27
33
 
28
34
  Options:
35
+ --limit N Maximum number of items to return (default: 20)
36
+ --cursor CURSOR Cursor for pagination (use nextCursor from previous response)
29
37
  --api-key KEY Exa API key (or set EXA_API_KEY env var)
30
- --output-format FMT Output format: json, pretty, or text (default: json)
38
+ --output-format FMT Output format: json, pretty, text, or toon (default: json)
31
39
  --help, -h Show this help message
32
40
 
33
41
  Examples:
34
42
  exa-ai webset-item-list ws_123
43
+ exa-ai webset-item-list ws_123 --limit 10
44
+ exa-ai webset-item-list ws_123 --limit 5 --cursor "abc123"
35
45
  exa-ai webset-item-list ws_123 --output-format pretty
36
- exa-ai webset-item-list ws_123 --output-format text
37
46
  HELP
38
47
  exit 0
39
48
  else
@@ -63,11 +72,16 @@ begin
63
72
  # Build client
64
73
  client = Exa::CLI::Base.build_client(api_key)
65
74
 
75
+ # Build list params
76
+ list_params = {}
77
+ list_params[:limit] = limit if limit
78
+ list_params[:cursor] = cursor if cursor
79
+
66
80
  # List items
67
- items = client.list_items(webset_id: webset_id)
81
+ collection = client.list_items(webset_id: webset_id, **list_params)
68
82
 
69
83
  # Format and output
70
- output = Exa::CLI::Formatters::WebsetItemFormatter.format_collection(items, output_format)
84
+ output = Exa::CLI::Formatters::WebsetItemFormatter.format_collection(collection, output_format)
71
85
  puts output
72
86
  $stdout.flush
73
87
 
@@ -104,11 +104,20 @@ def parse_args(argv)
104
104
  --entity TYPE Entity type: person, company, article, research_paper, custom
105
105
  --entity-description TXT Description for custom entity type (required with --entity custom)
106
106
  --criteria JSON Search criteria array (supports @file.json)
107
+ Format: [{"description":"criterion 1"},{"description":"criterion 2"}]
107
108
  --exclude JSON Items to exclude from results (supports @file.json)
109
+ Format: [{"source":"import|webset","id":"..."}]
108
110
  --scope JSON Limit search to specific sources (supports @file.json)
111
+ Format: [{"source":"import|webset","id":"..."}]
112
+ Filters this search to only items from these sources
113
+ With relationship (hop search):
114
+ [{"source":"webset","id":"ws_123",
115
+ "relationship":{"definition":"investors of","limit":3}}]
109
116
  --recall Estimate total available results
110
- --behavior TYPE "override" or "append" (default: override)
117
+ --behavior TYPE "override" (replace items) or "append" (add items)
118
+ Default: override when scope is present, append otherwise
111
119
  --metadata JSON Custom metadata (supports @file.json)
120
+ Format: {"key":"value"}
112
121
  --api-key KEY Exa API key (or set EXA_API_KEY env var)
113
122
  --output-format FMT Output format: json, pretty, or text (default: json)
114
123
  --help, -h Show this help message
@@ -121,11 +130,15 @@ def parse_args(argv)
121
130
  exa-ai webset-search-create ws_123 --query "tech CEOs" --entity person
122
131
  exa-ai webset-search-create ws_123 --query "Silicon Valley firms" --entity company
123
132
 
124
- # Search with custom entity type
125
- exa-ai webset-search-create ws_123 --query "Ford Mustang" \\
126
- --entity custom --entity-description "vintage cars"
133
+ # Scoped search (filter to specific import)
134
+ exa-ai webset-search-create ws_123 --query "CTOs" \\
135
+ --scope '[{"source":"import","id":"import_abc"}]'
127
136
 
128
- # Other options
137
+ # Hop search (find investors of companies in webset)
138
+ exa-ai webset-search-create ws_123 --query "investors" \\
139
+ --scope '[{"source":"webset","id":"ws_companies","relationship":{"definition":"investors of","limit":5}}]'
140
+
141
+ # Search with criteria and behavior
129
142
  exa-ai webset-search-create ws_123 --query "machine learning" --count 50
130
143
  exa-ai webset-search-create ws_123 --query "research" --behavior append --recall
131
144
  HELP
@@ -203,7 +216,7 @@ begin
203
216
  search = client.create_webset_search(webset_id: args[:webset_id], **search_params)
204
217
 
205
218
  # Format and output result
206
- output = Exa::CLI::Formatters::SearchFormatter.format(search, output_format)
219
+ output = Exa::CLI::Formatters::WebsetSearchFormatter.format(search, output_format)
207
220
  puts output
208
221
  $stdout.flush
209
222
 
@@ -78,7 +78,7 @@ begin
78
78
  search = client.get_webset_search(webset_id: webset_id, id: search_id)
79
79
 
80
80
  # Format and output
81
- output = Exa::CLI::Formatters::SearchFormatter.format(search, output_format)
81
+ output = Exa::CLI::Formatters::WebsetSearchFormatter.format(search, output_format)
82
82
  puts output
83
83
  $stdout.flush
84
84
 
@@ -4,24 +4,30 @@ module Exa
4
4
  module CLI
5
5
  module Formatters
6
6
  class AnswerFormatter
7
- def self.format(result, format)
7
+ def self.format(result, format, skip_citations: false)
8
8
  case format
9
9
  when "json"
10
- JSON.pretty_generate(result.to_h)
10
+ format_json(result, skip_citations: skip_citations)
11
11
  when "pretty"
12
- format_pretty(result)
12
+ format_pretty(result, skip_citations: skip_citations)
13
13
  when "text"
14
14
  format_text(result)
15
15
  when "toon"
16
16
  Exa::CLI::Base.encode_as_toon(result.to_h)
17
17
  else
18
- JSON.pretty_generate(result.to_h)
18
+ format_json(result, skip_citations: skip_citations)
19
19
  end
20
20
  end
21
21
 
22
22
  private
23
23
 
24
- def self.format_pretty(result)
24
+ def self.format_json(result, skip_citations: false)
25
+ hash = result.to_h
26
+ hash.delete(:citations) if skip_citations
27
+ JSON.pretty_generate(hash)
28
+ end
29
+
30
+ def self.format_pretty(result, skip_citations: false)
25
31
  output = []
26
32
  output << "Answer:"
27
33
  output << "-" * 60
@@ -34,15 +40,17 @@ module Exa
34
40
  end
35
41
  output << ""
36
42
 
37
- if result.citations && !result.citations.empty?
38
- output << "Citations:"
39
- output << "-" * 60
40
- result.citations.each_with_index do |citation, idx|
41
- output << "[#{idx + 1}] #{citation['title']}"
42
- output << " URL: #{citation['url']}"
43
- output << " Author: #{citation['author']}" if citation['author']
44
- output << " Date: #{citation['publishedDate']}" if citation['publishedDate']
45
- output << ""
43
+ unless skip_citations
44
+ if result.citations && !result.citations.empty?
45
+ output << "Citations:"
46
+ output << "-" * 60
47
+ result.citations.each_with_index do |citation, idx|
48
+ output << "[#{idx + 1}] #{citation['title']}"
49
+ output << " URL: #{citation['url']}"
50
+ output << " Author: #{citation['author']}" if citation['author']
51
+ output << " Date: #{citation['publishedDate']}" if citation['publishedDate']
52
+ output << ""
53
+ end
46
54
  end
47
55
  end
48
56
 
@@ -9,7 +9,7 @@ module Exa
9
9
  when "json"
10
10
  JSON.generate(enrichment.to_h)
11
11
  when "pretty"
12
- JSON.pretty_generate(enrichment.to_h)
12
+ format_as_pretty(enrichment)
13
13
  when "text"
14
14
  format_as_text(enrichment)
15
15
  when "toon"
@@ -24,7 +24,7 @@ module Exa
24
24
  when "json"
25
25
  JSON.generate(collection.to_h)
26
26
  when "pretty"
27
- JSON.pretty_generate(collection.to_h)
27
+ format_collection_as_pretty(collection)
28
28
  when "text"
29
29
  format_collection_as_text(collection)
30
30
  when "toon"
@@ -34,6 +34,31 @@ module Exa
34
34
  end
35
35
  end
36
36
 
37
+ def self.format_as_pretty(enrichment)
38
+ lines = []
39
+ lines << "Enrichment ID: #{enrichment.id}"
40
+ lines << "Webset ID: #{enrichment.webset_id}" if enrichment.webset_id
41
+ lines << "Status: #{enrichment.status}"
42
+ lines << "Title: #{enrichment.title}" if enrichment.title
43
+ lines << "Description: #{enrichment.description}" if enrichment.description
44
+ lines << "Format: #{enrichment.format}" if enrichment.format
45
+
46
+ if enrichment.options && !enrichment.options.empty?
47
+ lines << ""
48
+ lines << "Options (#{enrichment.options.length}):"
49
+ enrichment.options.each do |option|
50
+ lines << " • #{option['label']}" if option['label']
51
+ end
52
+ end
53
+
54
+ lines << ""
55
+ lines << "Created: #{enrichment.created_at}" if enrichment.created_at
56
+ lines << "Updated: #{enrichment.updated_at}" if enrichment.updated_at
57
+
58
+ lines.join("\n")
59
+ end
60
+ private_class_method :format_as_pretty
61
+
37
62
  def self.format_as_text(enrichment)
38
63
  lines = []
39
64
  lines << "Enrichment: #{enrichment.id}"
@@ -57,6 +82,33 @@ module Exa
57
82
  end
58
83
  private_class_method :format_as_text
59
84
 
85
+ def self.format_collection_as_pretty(collection)
86
+ lines = []
87
+ lines << "Enrichments (#{collection.data.length} items)"
88
+ lines << ""
89
+
90
+ collection.data.each_with_index do |enr, idx|
91
+ lines << "" if idx > 0 # Blank line between enrichments
92
+
93
+ lines << "Enrichment ID: #{enr['id']}"
94
+ lines << "Webset ID: #{enr['websetId']}" if enr['websetId']
95
+ lines << "Status: #{enr['status']}"
96
+ lines << "Title: #{enr['title']}" if enr['title']
97
+ lines << "Description: #{enr['description']}" if enr['description']
98
+ lines << "Format: #{enr['format']}" if enr['format']
99
+ lines << "Created: #{enr['createdAt']}" if enr['createdAt']
100
+ lines << "Updated: #{enr['updatedAt']}" if enr['updatedAt']
101
+ end
102
+
103
+ if collection.has_more
104
+ lines << ""
105
+ lines << "Next Cursor: #{collection.next_cursor}"
106
+ end
107
+
108
+ lines.join("\n")
109
+ end
110
+ private_class_method :format_collection_as_pretty
111
+
60
112
  def self.format_collection_as_text(collection)
61
113
  lines = ["Enrichments (#{collection.data.length} items):"]
62
114
  collection.data.each do |enr|
@@ -9,7 +9,7 @@ module Exa
9
9
  when "json"
10
10
  JSON.generate(import.to_h)
11
11
  when "pretty"
12
- JSON.pretty_generate(import.to_h)
12
+ format_as_pretty(import)
13
13
  when "text"
14
14
  format_as_text(import)
15
15
  when "toon"
@@ -24,7 +24,7 @@ module Exa
24
24
  when "json"
25
25
  JSON.generate(collection.to_h)
26
26
  when "pretty"
27
- JSON.pretty_generate(collection.to_h)
27
+ format_collection_as_pretty(collection)
28
28
  when "text"
29
29
  format_collection_as_text(collection)
30
30
  when "toon"
@@ -34,6 +34,43 @@ module Exa
34
34
  end
35
35
  end
36
36
 
37
+ def self.format_as_pretty(import)
38
+ lines = []
39
+ lines << "Import ID: #{import.id}"
40
+ lines << "Status: #{import.status}"
41
+ lines << "Title: #{import.title}" if import.title
42
+ lines << "Format: #{import.format}" if import.format
43
+
44
+ if import.entity
45
+ entity_type = import.entity['type'] || import.entity[:type]
46
+ lines << "Entity Type: #{entity_type}" if entity_type
47
+ end
48
+
49
+ lines << "Count: #{import.count}" if import.count
50
+
51
+ if import.failed?
52
+ lines << ""
53
+ lines << "Failure:"
54
+ lines << " Reason: #{import.failed_reason}" if import.failed_reason
55
+ lines << " Message: #{import.failed_message}" if import.failed_message
56
+ lines << " Failed At: #{import.failed_at}" if import.failed_at
57
+ end
58
+
59
+ if import.upload_url
60
+ lines << ""
61
+ lines << "Upload:"
62
+ lines << " URL: #{import.upload_url}"
63
+ lines << " Valid Until: #{import.upload_valid_until}" if import.upload_valid_until
64
+ end
65
+
66
+ lines << ""
67
+ lines << "Created: #{import.created_at}" if import.created_at
68
+ lines << "Updated: #{import.updated_at}" if import.updated_at
69
+
70
+ lines.join("\n")
71
+ end
72
+ private_class_method :format_as_pretty
73
+
37
74
  def self.format_as_text(import)
38
75
  lines = []
39
76
  lines << "Import: #{import.id}"
@@ -68,6 +105,37 @@ module Exa
68
105
  end
69
106
  private_class_method :format_as_text
70
107
 
108
+ def self.format_collection_as_pretty(collection)
109
+ lines = []
110
+ lines << "Imports (#{collection.data.length} items)"
111
+ lines << ""
112
+
113
+ collection.data.each_with_index do |imp, idx|
114
+ lines << "" if idx > 0 # Blank line between imports
115
+
116
+ lines << "Import ID: #{imp.id}"
117
+ lines << "Status: #{imp.status}"
118
+ lines << "Title: #{imp.title}" if imp.title
119
+ lines << "Format: #{imp.format}" if imp.format
120
+ lines << "Entity Type: #{imp.entity['type']}" if imp.entity && imp.entity['type']
121
+ lines << "Count: #{imp.count}" if imp.count
122
+ lines << "Created: #{imp.created_at}" if imp.created_at
123
+ lines << "Updated: #{imp.updated_at}" if imp.updated_at
124
+
125
+ if imp.status == 'failed'
126
+ lines << "Failed Reason: #{imp.failed_reason}" if imp.failed_reason
127
+ end
128
+ end
129
+
130
+ if collection.has_more
131
+ lines << ""
132
+ lines << "Next Cursor: #{collection.next_cursor}"
133
+ end
134
+
135
+ lines.join("\n")
136
+ end
137
+ private_class_method :format_collection_as_pretty
138
+
71
139
  def self.format_collection_as_text(collection)
72
140
  lines = ["Imports (#{collection.data.length} items):"]
73
141
  collection.data.each do |imp|
@@ -9,7 +9,7 @@ module Exa
9
9
  when "json"
10
10
  JSON.generate(monitor.to_h)
11
11
  when "pretty"
12
- JSON.pretty_generate(monitor.to_h)
12
+ format_as_pretty(monitor)
13
13
  when "text"
14
14
  format_as_text(monitor)
15
15
  when "toon"
@@ -24,7 +24,7 @@ module Exa
24
24
  when "json"
25
25
  JSON.generate(collection.to_h)
26
26
  when "pretty"
27
- JSON.pretty_generate(collection.to_h)
27
+ format_collection_as_pretty(collection)
28
28
  when "text"
29
29
  format_collection_as_text(collection)
30
30
  when "toon"
@@ -34,6 +34,35 @@ module Exa
34
34
  end
35
35
  end
36
36
 
37
+ def self.format_as_pretty(monitor)
38
+ lines = []
39
+ lines << "Monitor ID: #{monitor.id}"
40
+ lines << "Webset ID: #{monitor.webset_id}" if monitor.webset_id
41
+ lines << "Status: #{monitor.status}"
42
+
43
+ if monitor.cadence
44
+ lines << ""
45
+ lines << "Cadence:"
46
+ lines << " Cron: #{monitor.cadence['cron']}" if monitor.cadence['cron']
47
+ lines << " Timezone: #{monitor.cadence['timezone']}" if monitor.cadence['timezone']
48
+ end
49
+
50
+ if monitor.behavior
51
+ lines << ""
52
+ lines << "Behavior:"
53
+ lines << " Type: #{monitor.behavior['type']}" if monitor.behavior['type']
54
+ lines << " Query: #{monitor.behavior['query']}" if monitor.behavior['query']
55
+ lines << " Count: #{monitor.behavior['count']}" if monitor.behavior['count']
56
+ end
57
+
58
+ lines << ""
59
+ lines << "Created: #{monitor.created_at}" if monitor.created_at
60
+ lines << "Updated: #{monitor.updated_at}" if monitor.updated_at
61
+
62
+ lines.join("\n")
63
+ end
64
+ private_class_method :format_as_pretty
65
+
37
66
  def self.format_as_text(monitor)
38
67
  lines = []
39
68
  lines << "Monitor: #{monitor.id}"
@@ -60,6 +89,40 @@ module Exa
60
89
  end
61
90
  private_class_method :format_as_text
62
91
 
92
+ def self.format_collection_as_pretty(collection)
93
+ lines = []
94
+ lines << "Monitors (#{collection.data.length} items)"
95
+ lines << ""
96
+
97
+ collection.data.each_with_index do |mon, idx|
98
+ lines << "" if idx > 0 # Blank line between monitors
99
+
100
+ lines << "Monitor ID: #{mon['id']}"
101
+ lines << "Webset ID: #{mon['websetId']}" if mon['websetId']
102
+ lines << "Status: #{mon['status']}"
103
+
104
+ if mon['cadence']
105
+ lines << "Cron: #{mon['cadence']['cron']}" if mon['cadence']['cron']
106
+ lines << "Timezone: #{mon['cadence']['timezone']}" if mon['cadence']['timezone']
107
+ end
108
+
109
+ if mon['behavior']
110
+ lines << "Query: #{mon['behavior']['query']}" if mon['behavior']['query']
111
+ end
112
+
113
+ lines << "Created: #{mon['createdAt']}" if mon['createdAt']
114
+ lines << "Updated: #{mon['updatedAt']}" if mon['updatedAt']
115
+ end
116
+
117
+ if collection.has_more
118
+ lines << ""
119
+ lines << "Next Cursor: #{collection.next_cursor}"
120
+ end
121
+
122
+ lines.join("\n")
123
+ end
124
+ private_class_method :format_collection_as_pretty
125
+
63
126
  def self.format_collection_as_text(collection)
64
127
  lines = ["Monitors (#{collection.data.length} items):"]
65
128
  collection.data.each do |mon|
@@ -9,7 +9,7 @@ module Exa
9
9
  when "json"
10
10
  JSON.generate(monitor_run.to_h)
11
11
  when "pretty"
12
- JSON.pretty_generate(monitor_run.to_h)
12
+ format_as_pretty(monitor_run)
13
13
  when "text"
14
14
  format_as_text(monitor_run)
15
15
  when "toon"
@@ -24,7 +24,7 @@ module Exa
24
24
  when "json"
25
25
  JSON.generate(collection.to_h)
26
26
  when "pretty"
27
- JSON.pretty_generate(collection.to_h)
27
+ format_collection_as_pretty(collection)
28
28
  when "text"
29
29
  format_collection_as_text(collection)
30
30
  when "toon"
@@ -34,6 +34,27 @@ module Exa
34
34
  end
35
35
  end
36
36
 
37
+ def self.format_as_pretty(monitor_run)
38
+ lines = []
39
+ lines << "Monitor Run ID: #{monitor_run.id}"
40
+ lines << "Monitor ID: #{monitor_run.monitor_id}" if monitor_run.monitor_id
41
+ lines << "Status: #{monitor_run.status}"
42
+
43
+ lines << ""
44
+ lines << "Created: #{monitor_run.created_at}" if monitor_run.created_at
45
+ lines << "Updated: #{monitor_run.updated_at}" if monitor_run.updated_at
46
+ lines << "Completed: #{monitor_run.completed_at}" if monitor_run.completed_at
47
+
48
+ if monitor_run.failed?
49
+ lines << ""
50
+ lines << "Failed: #{monitor_run.failed_at}" if monitor_run.failed_at
51
+ lines << "Reason: #{monitor_run.failed_reason}" if monitor_run.failed_reason
52
+ end
53
+
54
+ lines.join("\n")
55
+ end
56
+ private_class_method :format_as_pretty
57
+
37
58
  def self.format_as_text(monitor_run)
38
59
  lines = []
39
60
  lines << "Monitor Run: #{monitor_run.id}"
@@ -53,6 +74,36 @@ module Exa
53
74
  end
54
75
  private_class_method :format_as_text
55
76
 
77
+ def self.format_collection_as_pretty(collection)
78
+ lines = []
79
+ lines << "Monitor Runs (#{collection.data.length} items)"
80
+ lines << ""
81
+
82
+ collection.data.each_with_index do |run, idx|
83
+ lines << "" if idx > 0 # Blank line between runs
84
+
85
+ lines << "Monitor Run ID: #{run['id']}"
86
+ lines << "Monitor ID: #{run['monitorId']}" if run['monitorId']
87
+ lines << "Status: #{run['status']}"
88
+ lines << "Created: #{run['createdAt']}" if run['createdAt']
89
+ lines << "Updated: #{run['updatedAt']}" if run['updatedAt']
90
+ lines << "Completed: #{run['completedAt']}" if run['completedAt']
91
+
92
+ if run['status'] == 'failed'
93
+ lines << "Failed: #{run['failedAt']}" if run['failedAt']
94
+ lines << "Reason: #{run['failedReason']}" if run['failedReason']
95
+ end
96
+ end
97
+
98
+ if collection.has_more
99
+ lines << ""
100
+ lines << "Next Cursor: #{collection.next_cursor}"
101
+ end
102
+
103
+ lines.join("\n")
104
+ end
105
+ private_class_method :format_collection_as_pretty
106
+
56
107
  def self.format_collection_as_text(collection)
57
108
  lines = ["Monitor Runs (#{collection.data.length} items):"]
58
109
  collection.data.each do |run|
@@ -24,7 +24,7 @@ module Exa
24
24
  when "json"
25
25
  JSON.generate(collection.to_h)
26
26
  when "pretty"
27
- JSON.pretty_generate(collection.to_h)
27
+ format_collection_as_pretty(collection)
28
28
  when "text"
29
29
  format_collection_as_text(collection)
30
30
  when "toon"
@@ -66,6 +66,66 @@ module Exa
66
66
  lines.join("\n")
67
67
  end
68
68
  private_class_method :format_collection_as_text
69
+
70
+ def self.format_collection_as_pretty(collection)
71
+ lines = []
72
+
73
+ # Header with count and pagination info
74
+ header = "Websets (#{collection.data.length} items)"
75
+ header += " - Page #{collection.has_more ? '1 of many' : '1 of 1'}" if collection.data.any?
76
+ lines << header
77
+
78
+ if collection.has_more
79
+ lines << "Next Cursor: #{collection.next_cursor}"
80
+ end
81
+
82
+ lines << ""
83
+
84
+ # Format each webset
85
+ collection.data.each_with_index do |ws, idx|
86
+ lines << "" if idx > 0 # Blank line between websets
87
+
88
+ lines << "Webset ID: #{ws['id']}"
89
+ lines << "Status: #{ws['status']}"
90
+ lines << "Title: #{ws['title']}" if ws['title']
91
+ lines << "External ID: #{ws['externalId']}" if ws['externalId']
92
+ lines << "Created: #{ws['createdAt']}" if ws['createdAt']
93
+ lines << "Updated: #{ws['updatedAt']}" if ws['updatedAt']
94
+
95
+ # Searches
96
+ if ws['searches'] && !ws['searches'].empty?
97
+ lines << ""
98
+ lines << "Searches (#{ws['searches'].length}):"
99
+ ws['searches'].each do |search|
100
+ status_indicator = case search['status']
101
+ when 'completed' then '✓'
102
+ when 'running' then '→'
103
+ when 'failed' then '✗'
104
+ else '•'
105
+ end
106
+ lines << " #{status_indicator} #{search['query']} (#{search['status']})" if search['query']
107
+ end
108
+ end
109
+
110
+ # Enrichments
111
+ if ws['enrichments'] && !ws['enrichments'].empty?
112
+ lines << "Enrichments: #{ws['enrichments'].length}"
113
+ end
114
+
115
+ # Monitors
116
+ if ws['monitors'] && !ws['monitors'].empty?
117
+ lines << "Monitors: #{ws['monitors'].length}"
118
+ end
119
+
120
+ # Imports
121
+ if ws['imports'] && !ws['imports'].empty?
122
+ lines << "Imports: #{ws['imports'].length}"
123
+ end
124
+ end
125
+
126
+ lines.join("\n")
127
+ end
128
+ private_class_method :format_collection_as_pretty
69
129
  end
70
130
  end
71
131
  end