exa-ai 0.4.1 → 0.6.0

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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -0
  3. data/exe/exa-ai +61 -7
  4. data/exe/exa-ai-answer +9 -8
  5. data/exe/exa-ai-context +6 -5
  6. data/exe/exa-ai-enrichment-cancel +1 -0
  7. data/exe/exa-ai-enrichment-create +1 -0
  8. data/exe/exa-ai-enrichment-delete +1 -0
  9. data/exe/exa-ai-enrichment-get +1 -0
  10. data/exe/exa-ai-enrichment-list +1 -0
  11. data/exe/exa-ai-enrichment-update +1 -0
  12. data/exe/exa-ai-find-similar +1 -0
  13. data/exe/exa-ai-get-contents +9 -8
  14. data/exe/exa-ai-import-create +235 -0
  15. data/exe/exa-ai-import-delete +92 -0
  16. data/exe/exa-ai-import-get +92 -0
  17. data/exe/exa-ai-import-list +72 -0
  18. data/exe/exa-ai-import-update +164 -0
  19. data/exe/exa-ai-monitor-create +223 -0
  20. data/exe/exa-ai-monitor-delete +101 -0
  21. data/exe/exa-ai-monitor-get +92 -0
  22. data/exe/exa-ai-monitor-list +90 -0
  23. data/exe/exa-ai-monitor-runs-get +103 -0
  24. data/exe/exa-ai-monitor-runs-list +110 -0
  25. data/exe/exa-ai-monitor-update +207 -0
  26. data/exe/exa-ai-research-get +7 -7
  27. data/exe/exa-ai-research-list +5 -5
  28. data/exe/exa-ai-research-start +8 -7
  29. data/exe/exa-ai-search +20 -13
  30. data/exe/exa-ai-webset-cancel +1 -0
  31. data/exe/exa-ai-webset-create +44 -6
  32. data/exe/exa-ai-webset-delete +1 -0
  33. data/exe/exa-ai-webset-get +1 -0
  34. data/exe/exa-ai-webset-item-get +1 -0
  35. data/exe/exa-ai-webset-item-list +1 -0
  36. data/exe/exa-ai-webset-list +1 -0
  37. data/exe/exa-ai-webset-search-cancel +1 -0
  38. data/exe/exa-ai-webset-search-create +1 -0
  39. data/exe/exa-ai-webset-search-get +1 -0
  40. data/exe/exa-ai-webset-update +1 -0
  41. data/lib/exa/cli/base.rb +8 -2
  42. data/lib/exa/cli/formatters/answer_formatter.rb +2 -0
  43. data/lib/exa/cli/formatters/contents_formatter.rb +2 -0
  44. data/lib/exa/cli/formatters/context_formatter.rb +2 -0
  45. data/lib/exa/cli/formatters/enrichment_formatter.rb +4 -0
  46. data/lib/exa/cli/formatters/import_formatter.rb +85 -0
  47. data/lib/exa/cli/formatters/monitor_formatter.rb +81 -0
  48. data/lib/exa/cli/formatters/monitor_run_formatter.rb +75 -0
  49. data/lib/exa/cli/formatters/research_formatter.rb +4 -0
  50. data/lib/exa/cli/formatters/search_formatter.rb +2 -0
  51. data/lib/exa/cli/formatters/webset_formatter.rb +4 -0
  52. data/lib/exa/cli/formatters/webset_item_formatter.rb +4 -0
  53. data/lib/exa/client.rb +137 -0
  54. data/lib/exa/constants/websets.rb +19 -0
  55. data/lib/exa/middleware/raise_error.rb +5 -0
  56. data/lib/exa/resources/import.rb +86 -0
  57. data/lib/exa/resources/import_collection.rb +33 -0
  58. data/lib/exa/resources/monitor.rb +48 -0
  59. data/lib/exa/resources/monitor_collection.rb +30 -0
  60. data/lib/exa/resources/monitor_run.rb +52 -0
  61. data/lib/exa/resources/monitor_run_collection.rb +30 -0
  62. data/lib/exa/services/search.rb +21 -1
  63. data/lib/exa/services/websets/create_validator.rb +5 -3
  64. data/lib/exa/services/websets/import_create.rb +40 -0
  65. data/lib/exa/services/websets/import_delete.rb +37 -0
  66. data/lib/exa/services/websets/import_get.rb +37 -0
  67. data/lib/exa/services/websets/import_list.rb +25 -0
  68. data/lib/exa/services/websets/import_update.rb +38 -0
  69. data/lib/exa/services/websets/import_upload.rb +58 -0
  70. data/lib/exa/services/websets/monitors/create.rb +42 -0
  71. data/lib/exa/services/websets/monitors/delete.rb +32 -0
  72. data/lib/exa/services/websets/monitors/get.rb +33 -0
  73. data/lib/exa/services/websets/monitors/list.rb +27 -0
  74. data/lib/exa/services/websets/monitors/runs/get.rb +37 -0
  75. data/lib/exa/services/websets/monitors/runs/list.rb +30 -0
  76. data/lib/exa/services/websets/monitors/update.rb +33 -0
  77. data/lib/exa/version.rb +1 -1
  78. data/lib/exa.rb +23 -0
  79. metadata +50 -1
@@ -39,7 +39,7 @@ def parse_args(argv)
39
39
  i += 2
40
40
  when "--help", "-h"
41
41
  puts <<~HELP
42
- Usage: exa-api research-start --instructions "TEXT" [OPTIONS]
42
+ Usage: exa-ai research-start --instructions "TEXT" [OPTIONS]
43
43
 
44
44
  Start a research task using Exa AI
45
45
 
@@ -54,10 +54,10 @@ def parse_args(argv)
54
54
  --help, -h Show this help message
55
55
 
56
56
  Examples:
57
- exa-api research-start --instructions "Find Ruby performance tips"
58
- exa-api research-start --instructions "Analyze AI trends" --wait --events
59
- exa-api research-start --instructions "Summarize papers" --model exa-research-pro --wait
60
- exa-api research-start --instructions "Find stats" --output-schema '{"type":"object"}'
57
+ exa-ai research-start --instructions "Find Ruby performance tips"
58
+ exa-ai research-start --instructions "Analyze AI trends" --wait --events
59
+ exa-ai research-start --instructions "Summarize papers" --model exa-research-pro --wait
60
+ exa-ai research-start --instructions "Find stats" --output-schema '{"type":"object"}'
61
61
  HELP
62
62
  exit 0
63
63
  else
@@ -75,7 +75,7 @@ begin
75
75
  # Validate instructions
76
76
  if args[:instructions].nil? || args[:instructions].empty?
77
77
  $stderr.puts "Error: --instructions flag is required"
78
- $stderr.puts "Run 'exa-api research-start --help' for usage information"
78
+ $stderr.puts "Run 'exa-ai research-start --help' for usage information"
79
79
  exit 1
80
80
  end
81
81
 
@@ -133,6 +133,7 @@ begin
133
133
  # Format and output final result
134
134
  output = Exa::CLI::Formatters::ResearchFormatter.format_task(final_task, output_format, show_events: args[:events])
135
135
  puts output
136
+ $stdout.flush
136
137
 
137
138
  # Exit with error code if task failed
138
139
  exit 1 if final_task.failed?
@@ -140,7 +141,7 @@ begin
140
141
  rescue Exa::CLI::Polling::TimeoutError => e
141
142
  $stderr.puts "\nError: Task did not complete within timeout period (5 minutes)"
142
143
  $stderr.puts "Task ID: #{task.research_id}"
143
- $stderr.puts "You can check the status later with: exa-api research-get #{task.research_id}"
144
+ $stderr.puts "You can check the status later with: exa-ai research-get #{task.research_id}"
144
145
  exit 1
145
146
  end
146
147
  else
data/exe/exa-ai-search CHANGED
@@ -20,7 +20,13 @@ def parse_args(argv)
20
20
  args[:num_results] = argv[i + 1].to_i
21
21
  i += 2
22
22
  when "--type"
23
- args[:type] = argv[i + 1]
23
+ search_type = argv[i + 1]
24
+ valid_types = ["fast", "deep", "keyword", "auto"]
25
+ unless valid_types.include?(search_type)
26
+ $stderr.puts "Error: Search type must be one of: #{valid_types.join(', ')}"
27
+ exit 1
28
+ end
29
+ args[:type] = search_type
24
30
  i += 2
25
31
  when "--category"
26
32
  category = argv[i + 1]
@@ -116,7 +122,7 @@ def parse_args(argv)
116
122
  i += 2
117
123
  when "--help", "-h"
118
124
  puts <<~HELP
119
- Usage: exa-api search QUERY [OPTIONS]
125
+ Usage: exa-ai search QUERY [OPTIONS]
120
126
 
121
127
  Search the web using Exa AI
122
128
 
@@ -125,7 +131,7 @@ def parse_args(argv)
125
131
 
126
132
  Options:
127
133
  --num-results N Number of results to return (default: 10)
128
- --type TYPE Search type: keyword, neural, fast, or auto (default: auto)
134
+ --type TYPE Search type: fast, deep, keyword, or auto (default: fast)
129
135
  --category CAT Focus on specific data category
130
136
  Options: "company", "research paper", "news", "pdf",
131
137
  "github", "tweet", "personal site", "linkedin profile",
@@ -160,15 +166,15 @@ def parse_args(argv)
160
166
  --help, -h Show this help message
161
167
 
162
168
  Examples:
163
- exa-api search "ruby programming"
164
- exa-api search "machine learning" --num-results 5 --type keyword
165
- exa-api search "Latest LLM research" --category "research paper"
166
- exa-api search "AI startups" --category company
167
- exa-api search "Anthropic" --linkedin company
168
- exa-api search "Dario Amodei" --linkedin person
169
- exa-api search "AI" --linkedin all
170
- exa-api search "AI research" --include-domains arxiv.org,scholar.google.com
171
- exa-api search "tutorials" --output-format pretty
169
+ exa-ai search "ruby programming"
170
+ exa-ai search "machine learning" --num-results 5 --type deep
171
+ exa-ai search "Latest LLM research" --category "research paper"
172
+ exa-ai search "AI startups" --category company
173
+ exa-ai search "Anthropic" --linkedin company
174
+ exa-ai search "Dario Amodei" --linkedin person
175
+ exa-ai search "AI" --linkedin all
176
+ exa-ai search "AI research" --include-domains arxiv.org,scholar.google.com
177
+ exa-ai search "tutorials" --output-format pretty
172
178
  HELP
173
179
  exit 0
174
180
  else
@@ -237,7 +243,7 @@ begin
237
243
  # Validate query
238
244
  if args[:query].nil? || args[:query].empty?
239
245
  $stderr.puts "Error: Query is required"
240
- $stderr.puts "Run 'exa-api search --help' for usage information"
246
+ $stderr.puts "Run 'exa-ai search --help' for usage information"
241
247
  exit 1
242
248
  end
243
249
 
@@ -281,6 +287,7 @@ begin
281
287
  # Format and output result
282
288
  output = Exa::CLI::Formatters::SearchFormatter.format(result, output_format)
283
289
  puts output
290
+ $stdout.flush
284
291
 
285
292
  rescue Exa::ConfigurationError => e
286
293
  $stderr.puts "Configuration error: #{e.message}"
@@ -68,6 +68,7 @@ begin
68
68
  # Format and output
69
69
  output = Exa::CLI::Formatters::WebsetFormatter.format(webset, output_format)
70
70
  puts output
71
+ $stdout.flush
71
72
 
72
73
  rescue Exa::NotFound => e
73
74
  $stderr.puts "Webset not found: #{e.message}"
@@ -46,6 +46,9 @@ def parse_args(argv)
46
46
  while i < argv.length
47
47
  arg = argv[i]
48
48
  case arg
49
+ when "--import"
50
+ args[:import] = argv[i + 1]
51
+ i += 2
49
52
  when "--search"
50
53
  args[:search] = parse_json_or_file(argv[i + 1])
51
54
  i += 2
@@ -72,12 +75,14 @@ def parse_args(argv)
72
75
  i += 2
73
76
  when "--help", "-h"
74
77
  puts <<~HELP
75
- Usage: exa-ai webset-create --search JSON [OPTIONS]
78
+ Usage: exa-ai webset-create (--search JSON | --import ID) [OPTIONS]
76
79
 
77
- Create a new webset with search criteria
80
+ Create a new webset from search criteria or an import
78
81
 
79
- Required:
82
+ Required (choose one):
80
83
  --search JSON Search configuration (supports @file.json)
84
+ --import ID Import or webset ID to create webset from
85
+ (accepts import_* or webset_* IDs)
81
86
 
82
87
  Options:
83
88
  --enrichments JSON Array of enrichment configs (supports @file.json)
@@ -90,9 +95,17 @@ def parse_args(argv)
90
95
  --help, -h Show this help message
91
96
 
92
97
  Examples:
98
+ # Create webset from search
93
99
  exa-ai webset-create --search '{"query":"AI startups","count":10}'
94
100
  exa-ai webset-create --search @search.json --enrichments @enrichments.json
95
101
  exa-ai webset-create --search @search.json --wait
102
+
103
+ # Create webset from import
104
+ exa-ai webset-create --import import_abc123
105
+ exa-ai webset-create --import import_def456 --enrichments @enrichments.json
106
+
107
+ # Create webset from existing webset
108
+ exa-ai webset-create --import webset_xyz789
96
109
  HELP
97
110
  exit 0
98
111
  else
@@ -109,8 +122,14 @@ begin
109
122
  args = parse_args(ARGV)
110
123
 
111
124
  # Validate required parameters
112
- unless args[:search]
113
- $stderr.puts "Error: --search is required"
125
+ if args[:search] && args[:import]
126
+ $stderr.puts "Error: Cannot specify both --search and --import"
127
+ $stderr.puts "Run 'exa-ai webset-create --help' for usage information"
128
+ exit 1
129
+ end
130
+
131
+ unless args[:search] || args[:import]
132
+ $stderr.puts "Error: Either --search or --import is required"
114
133
  $stderr.puts "Run 'exa-ai webset-create --help' for usage information"
115
134
  exit 1
116
135
  end
@@ -125,7 +144,25 @@ begin
125
144
  client = Exa::CLI::Base.build_client(api_key)
126
145
 
127
146
  # Prepare webset parameters
128
- webset_params = { search: args[:search] }
147
+ webset_params = {}
148
+
149
+ if args[:search]
150
+ webset_params[:search] = args[:search]
151
+ elsif args[:import]
152
+ # Detect source type from ID prefix and convert to API format
153
+ import_id = args[:import]
154
+ source = if import_id.start_with?("import_")
155
+ "import"
156
+ elsif import_id.start_with?("webset_")
157
+ "webset"
158
+ else
159
+ $stderr.puts "Error: Import ID must start with 'import_' or 'webset_'"
160
+ exit 1
161
+ end
162
+
163
+ webset_params[:import] = [{ source: source, id: import_id }]
164
+ end
165
+
129
166
  webset_params[:enrichments] = args[:enrichments] if args[:enrichments]
130
167
  webset_params[:exclude] = args[:exclude] if args[:exclude]
131
168
  webset_params[:externalId] = args[:external_id] if args[:external_id]
@@ -167,6 +204,7 @@ begin
167
204
  # Format and output result
168
205
  output = Exa::CLI::Formatters::WebsetFormatter.format(webset, output_format)
169
206
  puts output
207
+ $stdout.flush
170
208
 
171
209
  rescue Exa::ConfigurationError => e
172
210
  $stderr.puts "Configuration error: #{e.message}"
@@ -82,6 +82,7 @@ begin
82
82
  # Format and output
83
83
  output = Exa::CLI::Formatters::WebsetFormatter.format(result, output_format)
84
84
  puts output
85
+ $stdout.flush
85
86
 
86
87
  rescue Exa::NotFound => e
87
88
  $stderr.puts "Webset not found: #{e.message}"
@@ -68,6 +68,7 @@ begin
68
68
  # Format and output
69
69
  output = Exa::CLI::Formatters::WebsetFormatter.format(webset, output_format)
70
70
  puts output
71
+ $stdout.flush
71
72
 
72
73
  rescue Exa::NotFound => e
73
74
  $stderr.puts "Webset not found: #{e.message}"
@@ -80,6 +80,7 @@ begin
80
80
  # Format and output
81
81
  output = Exa::CLI::Formatters::WebsetItemFormatter.format(item, output_format)
82
82
  puts output
83
+ $stdout.flush
83
84
 
84
85
  rescue Exa::NotFound => e
85
86
  $stderr.puts "Item not found: #{e.message}"
@@ -69,6 +69,7 @@ begin
69
69
  # Format and output
70
70
  output = Exa::CLI::Formatters::WebsetItemFormatter.format_collection(items, output_format)
71
71
  puts output
72
+ $stdout.flush
72
73
 
73
74
  rescue Exa::NotFound => e
74
75
  $stderr.puts "Webset not found: #{e.message}"
@@ -65,6 +65,7 @@ begin
65
65
  # Format and output
66
66
  output = Exa::CLI::Formatters::WebsetFormatter.format_collection(collection, output_format)
67
67
  puts output
68
+ $stdout.flush
68
69
 
69
70
  rescue Exa::ConfigurationError => e
70
71
  $stderr.puts "Configuration error: #{e.message}"
@@ -79,6 +79,7 @@ begin
79
79
  # Format and output
80
80
  output = Exa::CLI::Formatters::SearchFormatter.format(search, output_format)
81
81
  puts output
82
+ $stdout.flush
82
83
 
83
84
  rescue Exa::NotFound => e
84
85
  $stderr.puts "Search not found: #{e.message}"
@@ -205,6 +205,7 @@ begin
205
205
  # Format and output result
206
206
  output = Exa::CLI::Formatters::SearchFormatter.format(search, output_format)
207
207
  puts output
208
+ $stdout.flush
208
209
 
209
210
  rescue Exa::ConfigurationError => e
210
211
  $stderr.puts "Configuration error: #{e.message}"
@@ -80,6 +80,7 @@ begin
80
80
  # Format and output
81
81
  output = Exa::CLI::Formatters::SearchFormatter.format(search, output_format)
82
82
  puts output
83
+ $stdout.flush
83
84
 
84
85
  rescue Exa::NotFound => e
85
86
  $stderr.puts "Search not found: #{e.message}"
@@ -111,6 +111,7 @@ begin
111
111
  # Format and output
112
112
  output = Exa::CLI::Formatters::WebsetFormatter.format(webset, output_format)
113
113
  puts output
114
+ $stdout.flush
114
115
 
115
116
  rescue Exa::NotFound => e
116
117
  $stderr.puts "Webset not found: #{e.message}"
data/lib/exa/cli/base.rb CHANGED
@@ -16,11 +16,11 @@ module Exa
16
16
  end
17
17
 
18
18
  # Resolve and validate output format
19
- # Valid formats: json, pretty, text
19
+ # Valid formats: json, pretty, text, toon
20
20
  # Defaults to json
21
21
  def self.resolve_output_format(flag_value)
22
22
  format = (flag_value || "json").downcase
23
- valid_formats = %w[json pretty text]
23
+ valid_formats = %w[json pretty text toon]
24
24
 
25
25
  return format if valid_formats.include?(format)
26
26
 
@@ -46,6 +46,12 @@ module Exa
46
46
  data.to_s
47
47
  end
48
48
  end
49
+
50
+ # Encode data as TOON format
51
+ def self.encode_as_toon(data)
52
+ require "toon" unless defined?(Toon)
53
+ Toon.encode(data)
54
+ end
49
55
  end
50
56
  end
51
57
  end
@@ -12,6 +12,8 @@ module Exa
12
12
  format_pretty(result)
13
13
  when "text"
14
14
  format_text(result)
15
+ when "toon"
16
+ Exa::CLI::Base.encode_as_toon(result.to_h)
15
17
  else
16
18
  JSON.pretty_generate(result.to_h)
17
19
  end
@@ -12,6 +12,8 @@ module Exa
12
12
  format_pretty(result)
13
13
  when "text"
14
14
  format_text(result)
15
+ when "toon"
16
+ Exa::CLI::Base.encode_as_toon(result.to_h)
15
17
  else
16
18
  JSON.pretty_generate(result.to_h)
17
19
  end
@@ -14,6 +14,8 @@ module Exa
14
14
  format_pretty(result)
15
15
  when "text"
16
16
  format_text(result)
17
+ when "toon"
18
+ Exa::CLI::Base.encode_as_toon(result.to_h)
17
19
  else
18
20
  JSON.pretty_generate(result.to_h)
19
21
  end
@@ -12,6 +12,8 @@ module Exa
12
12
  JSON.pretty_generate(enrichment.to_h)
13
13
  when "text"
14
14
  format_as_text(enrichment)
15
+ when "toon"
16
+ Exa::CLI::Base.encode_as_toon(enrichment.to_h)
15
17
  else
16
18
  raise ArgumentError, "Unknown output format: #{output_format}"
17
19
  end
@@ -25,6 +27,8 @@ module Exa
25
27
  JSON.pretty_generate(collection.to_h)
26
28
  when "text"
27
29
  format_collection_as_text(collection)
30
+ when "toon"
31
+ Exa::CLI::Base.encode_as_toon(collection.to_h)
28
32
  else
29
33
  raise ArgumentError, "Unknown output format: #{output_format}"
30
34
  end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exa
4
+ module CLI
5
+ module Formatters
6
+ class ImportFormatter
7
+ def self.format(import, output_format)
8
+ case output_format
9
+ when "json"
10
+ JSON.generate(import.to_h)
11
+ when "pretty"
12
+ JSON.pretty_generate(import.to_h)
13
+ when "text"
14
+ format_as_text(import)
15
+ when "toon"
16
+ Exa::CLI::Base.encode_as_toon(import.to_h)
17
+ else
18
+ raise ArgumentError, "Unknown output format: #{output_format}"
19
+ end
20
+ end
21
+
22
+ def self.format_collection(collection, output_format)
23
+ case output_format
24
+ when "json"
25
+ JSON.generate(collection.to_h)
26
+ when "pretty"
27
+ JSON.pretty_generate(collection.to_h)
28
+ when "text"
29
+ format_collection_as_text(collection)
30
+ when "toon"
31
+ Exa::CLI::Base.encode_as_toon(collection.to_h)
32
+ else
33
+ raise ArgumentError, "Unknown output format: #{output_format}"
34
+ end
35
+ end
36
+
37
+ def self.format_as_text(import)
38
+ lines = []
39
+ lines << "Import: #{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 << "\nFailure Details:"
53
+ lines << " Reason: #{import.failed_reason}" if import.failed_reason
54
+ lines << " Message: #{import.failed_message}" if import.failed_message
55
+ lines << " Failed At: #{import.failed_at}" if import.failed_at
56
+ end
57
+
58
+ if import.upload_url
59
+ lines << "\nUpload:"
60
+ lines << " URL: #{import.upload_url}"
61
+ lines << " Valid Until: #{import.upload_valid_until}" if import.upload_valid_until
62
+ end
63
+
64
+ lines << "\nCreated: #{import.created_at}" if import.created_at
65
+ lines << "Updated: #{import.updated_at}" if import.updated_at
66
+
67
+ lines.join("\n")
68
+ end
69
+ private_class_method :format_as_text
70
+
71
+ def self.format_collection_as_text(collection)
72
+ lines = ["Imports (#{collection.data.length} items):"]
73
+ collection.data.each do |imp|
74
+ lines << "\n #{imp.id}"
75
+ lines << " Status: #{imp.status}"
76
+ lines << " Title: #{imp.title}" if imp.title
77
+ lines << " Count: #{imp.count}" if imp.count
78
+ end
79
+ lines.join("\n")
80
+ end
81
+ private_class_method :format_collection_as_text
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exa
4
+ module CLI
5
+ module Formatters
6
+ class MonitorFormatter
7
+ def self.format(monitor, output_format)
8
+ case output_format
9
+ when "json"
10
+ JSON.generate(monitor.to_h)
11
+ when "pretty"
12
+ JSON.pretty_generate(monitor.to_h)
13
+ when "text"
14
+ format_as_text(monitor)
15
+ when "toon"
16
+ Exa::CLI::Base.encode_as_toon(monitor.to_h)
17
+ else
18
+ raise ArgumentError, "Unknown output format: #{output_format}"
19
+ end
20
+ end
21
+
22
+ def self.format_collection(collection, output_format)
23
+ case output_format
24
+ when "json"
25
+ JSON.generate(collection.to_h)
26
+ when "pretty"
27
+ JSON.pretty_generate(collection.to_h)
28
+ when "text"
29
+ format_collection_as_text(collection)
30
+ when "toon"
31
+ Exa::CLI::Base.encode_as_toon(collection.to_h)
32
+ else
33
+ raise ArgumentError, "Unknown output format: #{output_format}"
34
+ end
35
+ end
36
+
37
+ def self.format_as_text(monitor)
38
+ lines = []
39
+ lines << "Monitor: #{monitor.id}"
40
+ lines << "Webset: #{monitor.webset_id}" if monitor.webset_id
41
+ lines << "Status: #{monitor.status}"
42
+
43
+ if monitor.cadence
44
+ lines << "\nCadence:"
45
+ lines << " Cron: #{monitor.cadence['cron']}" if monitor.cadence['cron']
46
+ lines << " Timezone: #{monitor.cadence['timezone']}" if monitor.cadence['timezone']
47
+ end
48
+
49
+ if monitor.behavior
50
+ lines << "\nBehavior:"
51
+ lines << " Type: #{monitor.behavior['type']}" if monitor.behavior['type']
52
+ lines << " Query: #{monitor.behavior['query']}" if monitor.behavior['query']
53
+ lines << " Count: #{monitor.behavior['count']}" if monitor.behavior['count']
54
+ end
55
+
56
+ lines << "\nCreated: #{monitor.created_at}" if monitor.created_at
57
+ lines << "Updated: #{monitor.updated_at}" if monitor.updated_at
58
+
59
+ lines.join("\n")
60
+ end
61
+ private_class_method :format_as_text
62
+
63
+ def self.format_collection_as_text(collection)
64
+ lines = ["Monitors (#{collection.data.length} items):"]
65
+ collection.data.each do |mon|
66
+ lines << "\n #{mon['id']}"
67
+ lines << " Status: #{mon['status']}"
68
+ lines << " Webset: #{mon['websetId']}" if mon['websetId']
69
+ end
70
+
71
+ if collection.has_more
72
+ lines << "\nMore available (cursor: #{collection.next_cursor})"
73
+ end
74
+
75
+ lines.join("\n")
76
+ end
77
+ private_class_method :format_collection_as_text
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exa
4
+ module CLI
5
+ module Formatters
6
+ class MonitorRunFormatter
7
+ def self.format(monitor_run, output_format)
8
+ case output_format
9
+ when "json"
10
+ JSON.generate(monitor_run.to_h)
11
+ when "pretty"
12
+ JSON.pretty_generate(monitor_run.to_h)
13
+ when "text"
14
+ format_as_text(monitor_run)
15
+ when "toon"
16
+ Exa::CLI::Base.encode_as_toon(monitor_run.to_h)
17
+ else
18
+ raise ArgumentError, "Unknown output format: #{output_format}"
19
+ end
20
+ end
21
+
22
+ def self.format_collection(collection, output_format)
23
+ case output_format
24
+ when "json"
25
+ JSON.generate(collection.to_h)
26
+ when "pretty"
27
+ JSON.pretty_generate(collection.to_h)
28
+ when "text"
29
+ format_collection_as_text(collection)
30
+ when "toon"
31
+ Exa::CLI::Base.encode_as_toon(collection.to_h)
32
+ else
33
+ raise ArgumentError, "Unknown output format: #{output_format}"
34
+ end
35
+ end
36
+
37
+ def self.format_as_text(monitor_run)
38
+ lines = []
39
+ lines << "Monitor Run: #{monitor_run.id}"
40
+ lines << "Monitor: #{monitor_run.monitor_id}" if monitor_run.monitor_id
41
+ lines << "Status: #{monitor_run.status}"
42
+
43
+ lines << "\nCreated: #{monitor_run.created_at}" if monitor_run.created_at
44
+ lines << "Updated: #{monitor_run.updated_at}" if monitor_run.updated_at
45
+ lines << "Completed: #{monitor_run.completed_at}" if monitor_run.completed_at
46
+
47
+ if monitor_run.failed?
48
+ lines << "Failed: #{monitor_run.failed_at}" if monitor_run.failed_at
49
+ lines << "Reason: #{monitor_run.failed_reason}" if monitor_run.failed_reason
50
+ end
51
+
52
+ lines.join("\n")
53
+ end
54
+ private_class_method :format_as_text
55
+
56
+ def self.format_collection_as_text(collection)
57
+ lines = ["Monitor Runs (#{collection.data.length} items):"]
58
+ collection.data.each do |run|
59
+ lines << "\n #{run['id']}"
60
+ lines << " Status: #{run['status']}"
61
+ lines << " Completed: #{run['completedAt']}" if run['completedAt']
62
+ lines << " Failed: #{run['failedReason']}" if run['failedReason']
63
+ end
64
+
65
+ if collection.has_more
66
+ lines << "\nMore available (cursor: #{collection.next_cursor})"
67
+ end
68
+
69
+ lines.join("\n")
70
+ end
71
+ private_class_method :format_collection_as_text
72
+ end
73
+ end
74
+ end
75
+ end
@@ -10,6 +10,8 @@ module Exa
10
10
  format_task_pretty(task, show_events: show_events)
11
11
  when "text"
12
12
  format_task_text(task, show_events: show_events)
13
+ when "toon"
14
+ Exa::CLI::Base.encode_as_toon(task.to_h)
13
15
  else
14
16
  JSON.pretty_generate(task.to_h)
15
17
  end
@@ -23,6 +25,8 @@ module Exa
23
25
  format_list_pretty(list)
24
26
  when "text"
25
27
  format_list_text(list)
28
+ when "toon"
29
+ Exa::CLI::Base.encode_as_toon(list.to_h)
26
30
  else
27
31
  JSON.pretty_generate(list.to_h)
28
32
  end
@@ -12,6 +12,8 @@ module Exa
12
12
  format_pretty(result)
13
13
  when "text"
14
14
  format_text(result)
15
+ when "toon"
16
+ Exa::CLI::Base.encode_as_toon(result.to_h)
15
17
  else
16
18
  JSON.pretty_generate(result.to_h)
17
19
  end