exa-ai 0.5.0 → 0.6.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -0
  3. data/exe/exa-ai +55 -1
  4. data/exe/exa-ai-enrichment-create +0 -10
  5. data/exe/exa-ai-import-create +253 -0
  6. data/exe/exa-ai-import-delete +92 -0
  7. data/exe/exa-ai-import-get +92 -0
  8. data/exe/exa-ai-import-list +72 -0
  9. data/exe/exa-ai-import-update +164 -0
  10. data/exe/exa-ai-monitor-create +223 -0
  11. data/exe/exa-ai-monitor-delete +101 -0
  12. data/exe/exa-ai-monitor-get +92 -0
  13. data/exe/exa-ai-monitor-list +90 -0
  14. data/exe/exa-ai-monitor-runs-get +103 -0
  15. data/exe/exa-ai-monitor-runs-list +110 -0
  16. data/exe/exa-ai-monitor-update +207 -0
  17. data/exe/exa-ai-webset-create +64 -8
  18. data/exe/exa-ai-webset-search-create +19 -6
  19. data/exe/exa-ai-webset-search-get +1 -1
  20. data/lib/exa/cli/base.rb +8 -2
  21. data/lib/exa/cli/formatters/answer_formatter.rb +2 -0
  22. data/lib/exa/cli/formatters/contents_formatter.rb +2 -0
  23. data/lib/exa/cli/formatters/context_formatter.rb +2 -0
  24. data/lib/exa/cli/formatters/enrichment_formatter.rb +58 -2
  25. data/lib/exa/cli/formatters/import_formatter.rb +153 -0
  26. data/lib/exa/cli/formatters/monitor_formatter.rb +144 -0
  27. data/lib/exa/cli/formatters/monitor_run_formatter.rb +126 -0
  28. data/lib/exa/cli/formatters/research_formatter.rb +4 -0
  29. data/lib/exa/cli/formatters/search_formatter.rb +2 -0
  30. data/lib/exa/cli/formatters/webset_formatter.rb +65 -1
  31. data/lib/exa/cli/formatters/webset_item_formatter.rb +54 -2
  32. data/lib/exa/cli/formatters/webset_search_formatter.rb +57 -0
  33. data/lib/exa/client.rb +137 -0
  34. data/lib/exa/constants/websets.rb +19 -0
  35. data/lib/exa/resources/import.rb +86 -0
  36. data/lib/exa/resources/import_collection.rb +33 -0
  37. data/lib/exa/resources/monitor.rb +48 -0
  38. data/lib/exa/resources/monitor_collection.rb +30 -0
  39. data/lib/exa/resources/monitor_run.rb +52 -0
  40. data/lib/exa/resources/monitor_run_collection.rb +30 -0
  41. data/lib/exa/services/websets/create_validator.rb +20 -3
  42. data/lib/exa/services/websets/import_create.rb +40 -0
  43. data/lib/exa/services/websets/import_delete.rb +37 -0
  44. data/lib/exa/services/websets/import_get.rb +37 -0
  45. data/lib/exa/services/websets/import_list.rb +25 -0
  46. data/lib/exa/services/websets/import_update.rb +38 -0
  47. data/lib/exa/services/websets/import_upload.rb +58 -0
  48. data/lib/exa/services/websets/monitors/create.rb +42 -0
  49. data/lib/exa/services/websets/monitors/delete.rb +32 -0
  50. data/lib/exa/services/websets/monitors/get.rb +33 -0
  51. data/lib/exa/services/websets/monitors/list.rb +27 -0
  52. data/lib/exa/services/websets/monitors/runs/get.rb +37 -0
  53. data/lib/exa/services/websets/monitors/runs/list.rb +30 -0
  54. data/lib/exa/services/websets/monitors/update.rb +33 -0
  55. data/lib/exa/version.rb +1 -1
  56. data/lib/exa.rb +24 -0
  57. metadata +51 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f9d0670c6b642073a66e32d8ecdd46702931e4b17f66bd6970b976a51ec5c56
4
- data.tar.gz: 2f9126068c6e0672cf7ac67b2d18e188396dbd3785285c4683b2deb99b97d14d
3
+ metadata.gz: 4f55e9efe411da4b9eaf3018791aa7819fc8872c69e32369627014594eb23670
4
+ data.tar.gz: 0d074ce4bb6eaa2902b80fe5df239be717f182c3703ebfcd6c45944de7cd1245
5
5
  SHA512:
6
- metadata.gz: 70e7be7fd10d14c69dd1b3125e453c9aa5a7233fb5f618233b8e3af0b42c7546a02b7cb34b9a20f9bb25b0f235f5b6fcbecefbaa5c33393720a47200b1443d93
7
- data.tar.gz: 3ef41b82e7126b4f875a3acddeaf046293a75e2d6cae3a03ea1c3ab46dc5ba9d8ade004add9e5f588876b7cdc4bf7a6c4f27d6be08a42b31e29a7ec3a987dd4f
6
+ metadata.gz: 732d915bf1eadcabff77ae2dcf7c573d426021bea3dac1fe0b2013958dde5a53129c62675ff66279b5204233c970b988ea72ad29ef94bb4b5219cba55910145b
7
+ data.tar.gz: f4f73347c282e2ebb2209afd42a02e1fb253e9d682a5959ce1cd2ea27519f132c156fb897bbd3177d24f4b88bd06874afd76b81bf70ccb225dcb3ad64ec6249b
data/README.md CHANGED
@@ -128,6 +128,15 @@ exa-ai enrichment-get WEBSET_ID ENRICHMENT_ID
128
128
  exa-ai enrichment-update WEBSET_ID ENRICHMENT_ID --description "Updated description"
129
129
  exa-ai enrichment-delete WEBSET_ID ENRICHMENT_ID --force
130
130
  exa-ai enrichment-cancel WEBSET_ID ENRICHMENT_ID
131
+
132
+ # Webset Imports
133
+ exa-ai webset-import-create companies.csv --count 100 --title "My Companies" --format csv --entity-type company
134
+ exa-ai webset-import-create data.csv --count 50 --title "Tech Startups" --format csv --entity-type company --csv-identifier 0
135
+ exa-ai webset-import-create import.csv --count 100 --title "Import" --format csv --entity-type company --metadata '{"source":"crm"}' --quiet
136
+ exa-ai webset-import-list
137
+ exa-ai webset-import-get IMPORT_ID
138
+ exa-ai webset-import-update IMPORT_ID --title "Updated Title"
139
+ exa-ai webset-import-delete IMPORT_ID
131
140
  ```
132
141
 
133
142
  ## Features
@@ -150,6 +159,7 @@ The gem provides complete access to Exa's API endpoints:
150
159
  - **Webset Searches** — Run searches within websets and manage search tasks
151
160
  - **Webset Items** — List, retrieve, and manage individual items in websets
152
161
  - **Enrichments** — Create and manage AI-powered data enrichment tasks on websets
162
+ - **Imports** — Upload CSV files to import external data into websets
153
163
 
154
164
  ## Error Handling
155
165
 
data/exe/exa-ai CHANGED
@@ -32,7 +32,19 @@ module ExaCLI
32
32
  "enrichment-list" => "List enrichments",
33
33
  "enrichment-update" => "Update an enrichment",
34
34
  "enrichment-delete" => "Delete an enrichment",
35
- "enrichment-cancel" => "Cancel an enrichment"
35
+ "enrichment-cancel" => "Cancel an enrichment",
36
+ "import-create" => "Create a new import",
37
+ "import-list" => "List imports",
38
+ "import-get" => "Get import details",
39
+ "import-update" => "Update an import",
40
+ "import-delete" => "Delete an import",
41
+ "monitor-create" => "Create a webset monitor",
42
+ "monitor-get" => "Get monitor details",
43
+ "monitor-list" => "List monitors",
44
+ "monitor-update" => "Update a monitor",
45
+ "monitor-delete" => "Delete a monitor",
46
+ "monitor-runs-list" => "List monitor runs",
47
+ "monitor-runs-get" => "Get monitor run details"
36
48
  }.freeze
37
49
 
38
50
  def self.run
@@ -98,6 +110,30 @@ module ExaCLI
98
110
  exec File.expand_path("../exa-ai-enrichment-delete", __FILE__), *ARGV[1..]
99
111
  when "enrichment-cancel"
100
112
  exec File.expand_path("../exa-ai-enrichment-cancel", __FILE__), *ARGV[1..]
113
+ when "import-create"
114
+ exec File.expand_path("../exa-ai-import-create", __FILE__), *ARGV[1..]
115
+ when "import-list"
116
+ exec File.expand_path("../exa-ai-import-list", __FILE__), *ARGV[1..]
117
+ when "import-get"
118
+ exec File.expand_path("../exa-ai-import-get", __FILE__), *ARGV[1..]
119
+ when "import-update"
120
+ exec File.expand_path("../exa-ai-import-update", __FILE__), *ARGV[1..]
121
+ when "import-delete"
122
+ exec File.expand_path("../exa-ai-import-delete", __FILE__), *ARGV[1..]
123
+ when "monitor-create"
124
+ exec File.expand_path("../exa-ai-monitor-create", __FILE__), *ARGV[1..]
125
+ when "monitor-get"
126
+ exec File.expand_path("../exa-ai-monitor-get", __FILE__), *ARGV[1..]
127
+ when "monitor-list"
128
+ exec File.expand_path("../exa-ai-monitor-list", __FILE__), *ARGV[1..]
129
+ when "monitor-update"
130
+ exec File.expand_path("../exa-ai-monitor-update", __FILE__), *ARGV[1..]
131
+ when "monitor-delete"
132
+ exec File.expand_path("../exa-ai-monitor-delete", __FILE__), *ARGV[1..]
133
+ when "monitor-runs-list"
134
+ exec File.expand_path("../exa-ai-monitor-runs-list", __FILE__), *ARGV[1..]
135
+ when "monitor-runs-get"
136
+ exec File.expand_path("../exa-ai-monitor-runs-get", __FILE__), *ARGV[1..]
101
137
  else
102
138
  print_error_for_command(ARGV[0])
103
139
  exit 1
@@ -154,6 +190,24 @@ module ExaCLI
154
190
  ["enrichment-cancel", "Cancel an enrichment"]
155
191
  ])
156
192
 
193
+ print_command_section("Imports", [
194
+ ["import-create", "Create a new import"],
195
+ ["import-list", "List imports"],
196
+ ["import-get", "Get import details"],
197
+ ["import-update", "Update an import"],
198
+ ["import-delete", "Delete an import"]
199
+ ])
200
+
201
+ print_command_section("Webset Monitors", [
202
+ ["monitor-create", "Create a webset monitor"],
203
+ ["monitor-get", "Get monitor details"],
204
+ ["monitor-list", "List monitors"],
205
+ ["monitor-update", "Update a monitor"],
206
+ ["monitor-delete", "Delete a monitor"],
207
+ ["monitor-runs-list", "List monitor runs"],
208
+ ["monitor-runs-get", "Get monitor run details"]
209
+ ])
210
+
157
211
  puts "Global Options:"
158
212
  puts " --help, -h Show this help message"
159
213
  puts " --version Show version number"
@@ -51,9 +51,7 @@ def parse_args(argv)
51
51
  --format TYPE One of: #{VALID_FORMATS.join(', ')}
52
52
 
53
53
  Options:
54
- --title TEXT Display title
55
54
  --options JSON Array of {label: "..."} (required if format=options, supports @file.json)
56
- --instructions TEXT Additional instructions
57
55
  --metadata JSON Custom metadata (supports @file.json)
58
56
  --wait Wait for enrichment to complete
59
57
  --api-key KEY Exa API key (or set EXA_API_KEY env var)
@@ -91,15 +89,9 @@ def parse_args(argv)
91
89
  when "--format"
92
90
  args[:format] = argv[i + 1]
93
91
  i += 2
94
- when "--title"
95
- args[:title] = argv[i + 1]
96
- i += 2
97
92
  when "--options"
98
93
  args[:options] = parse_json_or_file(argv[i + 1])
99
94
  i += 2
100
- when "--instructions"
101
- args[:instructions] = argv[i + 1]
102
- i += 2
103
95
  when "--metadata"
104
96
  args[:metadata] = parse_json_or_file(argv[i + 1])
105
97
  i += 2
@@ -170,9 +162,7 @@ begin
170
162
  description: args[:description],
171
163
  format: args[:format]
172
164
  }
173
- enrichment_params[:title] = args[:title] if args[:title]
174
165
  enrichment_params[:options] = args[:options] if args[:options]
175
- enrichment_params[:instructions] = args[:instructions] if args[:instructions]
176
166
  enrichment_params[:metadata] = args[:metadata] if args[:metadata]
177
167
 
178
168
  # Create enrichment
@@ -0,0 +1,253 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "exa-ai"
5
+
6
+ VALID_FORMATS = Exa::Constants::Websets::IMPORT_FORMATS
7
+ VALID_ENTITY_TYPES = Exa::Constants::Websets::ENTITY_TYPES
8
+
9
+ # Recursively convert hash keys from strings to symbols
10
+ def deep_symbolize_keys(obj)
11
+ case obj
12
+ when Hash
13
+ obj.each_with_object({}) do |(key, value), result|
14
+ result[key.to_sym] = deep_symbolize_keys(value)
15
+ end
16
+ when Array
17
+ obj.map { |item| deep_symbolize_keys(item) }
18
+ else
19
+ obj
20
+ end
21
+ end
22
+
23
+ # Parse JSON string or load from file (supports @file.json syntax)
24
+ def parse_json_or_file(value)
25
+ json_data = if value.start_with?("@")
26
+ file_path = value[1..]
27
+ JSON.parse(File.read(file_path))
28
+ else
29
+ JSON.parse(value)
30
+ end
31
+ deep_symbolize_keys(json_data)
32
+ rescue JSON::ParserError => e
33
+ $stderr.puts "Error: Invalid JSON: #{e.message}"
34
+ exit 1
35
+ rescue Errno::ENOENT => e
36
+ $stderr.puts "Error: File not found: #{e.message}"
37
+ exit 1
38
+ end
39
+
40
+ # Parse command-line arguments
41
+ def parse_args(argv)
42
+ # Check for help first
43
+ if argv.include?("--help") || argv.include?("-h")
44
+ puts <<~HELP
45
+ Usage: exa-ai import-create FILE [OPTIONS]
46
+
47
+ Create a new import and upload external data file
48
+
49
+ Arguments:
50
+ FILE Path to the CSV file to upload
51
+
52
+ Required:
53
+ --count N Number of entities in the import
54
+ --title TEXT Display title
55
+ --format TYPE Format type (default: csv, options: #{VALID_FORMATS.join(', ')})
56
+ --entity-type TYPE Entity type (options: #{VALID_ENTITY_TYPES.join(', ')})
57
+
58
+ Options:
59
+ --entity-description TXT Description for custom entity type (required with --entity-type custom)
60
+ --csv-identifier N CSV column identifier (0-indexed)
61
+ --metadata JSON Custom metadata (supports @file.json)
62
+ --quiet Suppress normal output (only show errors)
63
+ --api-key KEY Exa API key (or set EXA_API_KEY env var)
64
+ --output-format FMT Output format: json, pretty, or text (default: json)
65
+ --help, -h Show this help message
66
+
67
+ Examples:
68
+ exa-ai import-create data.csv --count 100 --title "My Companies" --format csv --entity-type company
69
+ exa-ai import-create companies.csv --count 50 --title "Tech Startups" --format csv --entity-type company --csv-identifier 0
70
+ exa-ai import-create import.csv --count 100 --title "Import" --format csv --entity-type company --metadata '{"source":"crm"}' --quiet
71
+ HELP
72
+ exit 0
73
+ end
74
+
75
+ # First argument should be the file path
76
+ if argv.empty? || argv[0].start_with?("--")
77
+ $stderr.puts "Error: FILE argument is required"
78
+ $stderr.puts "Run 'exa-ai import-create --help' for usage information"
79
+ exit 1
80
+ end
81
+
82
+ args = {
83
+ file_path: argv[0],
84
+ output_format: "json",
85
+ api_key: nil,
86
+ format: "csv",
87
+ quiet: false
88
+ }
89
+
90
+ i = 1 # Start after the file path
91
+ while i < argv.length
92
+ arg = argv[i]
93
+ case arg
94
+ when "--count"
95
+ args[:count] = argv[i + 1].to_i
96
+ i += 2
97
+ when "--title"
98
+ args[:title] = argv[i + 1]
99
+ i += 2
100
+ when "--format"
101
+ args[:format] = argv[i + 1]
102
+ i += 2
103
+ when "--entity-type"
104
+ args[:entity_type] = argv[i + 1]
105
+ i += 2
106
+ when "--entity-description"
107
+ args[:entity_description] = argv[i + 1]
108
+ i += 2
109
+ when "--csv-identifier"
110
+ args[:csv_identifier] = argv[i + 1].to_i
111
+ i += 2
112
+ when "--metadata"
113
+ args[:metadata] = parse_json_or_file(argv[i + 1])
114
+ i += 2
115
+ when "--quiet"
116
+ args[:quiet] = true
117
+ i += 1
118
+ when "--api-key"
119
+ args[:api_key] = argv[i + 1]
120
+ i += 2
121
+ when "--output-format"
122
+ args[:output_format] = argv[i + 1]
123
+ i += 2
124
+ else
125
+ $stderr.puts "Unknown option: #{arg}"
126
+ exit 1
127
+ end
128
+ end
129
+
130
+ args
131
+ end
132
+
133
+ # Main execution
134
+ begin
135
+ args = parse_args(ARGV)
136
+
137
+ # Validate required parameters
138
+ unless args[:count]
139
+ $stderr.puts "Error: --count is required"
140
+ $stderr.puts "Run 'exa-ai import-create --help' for usage information"
141
+ exit 1
142
+ end
143
+
144
+ unless args[:title]
145
+ $stderr.puts "Error: --title is required"
146
+ $stderr.puts "Run 'exa-ai import-create --help' for usage information"
147
+ exit 1
148
+ end
149
+
150
+ unless args[:entity_type]
151
+ $stderr.puts "Error: --entity-type is required"
152
+ $stderr.puts "Run 'exa-ai import-create --help' for usage information"
153
+ exit 1
154
+ end
155
+
156
+ # Validate format
157
+ unless VALID_FORMATS.include?(args[:format])
158
+ $stderr.puts "Error: format must be one of: #{VALID_FORMATS.join(', ')}"
159
+ exit 1
160
+ end
161
+
162
+ # Validate entity type
163
+ unless VALID_ENTITY_TYPES.include?(args[:entity_type])
164
+ $stderr.puts "Error: entity-type must be one of: #{VALID_ENTITY_TYPES.join(', ')}"
165
+ exit 1
166
+ end
167
+
168
+ # Validate entity-description for custom entity type
169
+ if args[:entity_type] == "custom"
170
+ unless args[:entity_description]
171
+ $stderr.puts "Error: --entity-description is required when --entity-type is 'custom'"
172
+ $stderr.puts "Run 'exa-ai import-create --help' for usage information"
173
+ exit 1
174
+ end
175
+ elsif args[:entity_description]
176
+ $stderr.puts "Warning: --entity-description is only used with --entity-type custom (ignoring)"
177
+ end
178
+
179
+ # Validate file exists
180
+ unless File.exist?(args[:file_path])
181
+ $stderr.puts "Error: File not found: #{args[:file_path]}"
182
+ exit 1
183
+ end
184
+
185
+ # Resolve API key
186
+ api_key = Exa::CLI::Base.resolve_api_key(args[:api_key])
187
+
188
+ # Resolve output format
189
+ output_format = Exa::CLI::Base.resolve_output_format(args[:output_format])
190
+
191
+ # Build client
192
+ client = Exa::CLI::Base.build_client(api_key)
193
+
194
+ # Prepare import parameters
195
+ entity = { type: args[:entity_type] }
196
+ entity[:description] = args[:entity_description] if args[:entity_description]
197
+
198
+ import_params = {
199
+ file_path: args[:file_path],
200
+ count: args[:count],
201
+ title: args[:title],
202
+ format: args[:format],
203
+ entity: entity
204
+ }
205
+ import_params[:metadata] = args[:metadata] if args[:metadata]
206
+
207
+ # Add CSV config if csv_identifier provided
208
+ if args[:csv_identifier]
209
+ import_params[:csv] = { identifier: args[:csv_identifier] }
210
+ end
211
+
212
+ # Show upload message unless quiet
213
+ unless args[:quiet]
214
+ file_size = File.size(args[:file_path])
215
+ $stderr.puts "Uploading #{args[:file_path]} (#{file_size} bytes)..."
216
+ end
217
+
218
+ # Upload import
219
+ import = client.upload_import(**import_params)
220
+
221
+ # Show success message unless quiet
222
+ unless args[:quiet]
223
+ $stderr.puts "Upload complete. Import ID: #{import.id}"
224
+ end
225
+
226
+ # Format and output result (unless quiet)
227
+ unless args[:quiet]
228
+ output = Exa::CLI::Formatters::ImportFormatter.format(import, output_format)
229
+ puts output
230
+ end
231
+
232
+ rescue Exa::ConfigurationError => e
233
+ $stderr.puts "Configuration error: #{e.message}"
234
+ exit 1
235
+ rescue Exa::Unauthorized => e
236
+ $stderr.puts "Authentication error: #{e.message}"
237
+ $stderr.puts "Check your API key (set EXA_API_KEY or use --api-key)"
238
+ exit 1
239
+ rescue Exa::ClientError => e
240
+ $stderr.puts "Client error: #{e.message}"
241
+ exit 1
242
+ rescue Exa::ServerError => e
243
+ $stderr.puts "Server error: #{e.message}"
244
+ $stderr.puts "The Exa API may be experiencing issues. Please try again later."
245
+ exit 1
246
+ rescue Exa::Error => e
247
+ $stderr.puts "Error: #{e.message}"
248
+ exit 1
249
+ rescue StandardError => e
250
+ $stderr.puts "Unexpected error: #{e.message}"
251
+ $stderr.puts e.backtrace.first(5) if ENV["DEBUG"]
252
+ exit 1
253
+ end
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "exa-ai"
5
+
6
+ # Parse arguments
7
+ import_id = nil
8
+ api_key = nil
9
+ output_format = "json"
10
+
11
+ args = ARGV.dup
12
+ while args.any?
13
+ arg = args.shift
14
+ case arg
15
+ when "--api-key"
16
+ api_key = args.shift
17
+ when "--output-format"
18
+ output_format = args.shift
19
+ when "--help", "-h"
20
+ puts <<~HELP
21
+ Usage: exa-ai import-delete <import_id> [OPTIONS]
22
+
23
+ Delete an import
24
+
25
+ Arguments:
26
+ import_id ID of the import to delete (required)
27
+
28
+ Options:
29
+ --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)
31
+ --help, -h Show this help message
32
+
33
+ Examples:
34
+ exa-ai import-delete imp_123
35
+ exa-ai import-delete imp_123 --output-format text
36
+ HELP
37
+ exit 0
38
+ else
39
+ # First positional argument is import_id
40
+ if import_id.nil?
41
+ import_id = arg
42
+ else
43
+ $stderr.puts "Unknown option: #{arg}"
44
+ exit 1
45
+ end
46
+ end
47
+ end
48
+
49
+ # Validate
50
+ if import_id.nil?
51
+ $stderr.puts "Error: import_id argument is required"
52
+ $stderr.puts "Usage: exa-ai import-delete <import_id> [OPTIONS]"
53
+ $stderr.puts "Try 'exa-ai import-delete --help' for more information"
54
+ exit 1
55
+ end
56
+
57
+ begin
58
+ # Resolve API key and format
59
+ api_key = Exa::CLI::Base.resolve_api_key(api_key)
60
+ output_format = Exa::CLI::Base.resolve_output_format(output_format)
61
+
62
+ # Build client
63
+ client = Exa::CLI::Base.build_client(api_key)
64
+
65
+ # Delete import
66
+ import = client.delete_import(import_id)
67
+
68
+ # Format and output
69
+ output = Exa::CLI::Formatters::ImportFormatter.format(import, output_format)
70
+ puts output
71
+
72
+ rescue Exa::NotFound => e
73
+ $stderr.puts "Import not found: #{e.message}"
74
+ exit 1
75
+ rescue Exa::Unauthorized => e
76
+ $stderr.puts "Authentication error: #{e.message}"
77
+ $stderr.puts "Check your API key (set EXA_API_KEY or use --api-key)"
78
+ exit 1
79
+ rescue Exa::ClientError => e
80
+ $stderr.puts "Client error: #{e.message}"
81
+ exit 1
82
+ rescue Exa::ServerError => e
83
+ $stderr.puts "Server error: #{e.message}"
84
+ exit 1
85
+ rescue Exa::Error => e
86
+ $stderr.puts "Error: #{e.message}"
87
+ exit 1
88
+ rescue StandardError => e
89
+ $stderr.puts "Unexpected error: #{e.message}"
90
+ $stderr.puts e.backtrace.first(5) if ENV["DEBUG"]
91
+ exit 1
92
+ end
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "exa-ai"
5
+
6
+ # Parse arguments
7
+ import_id = nil
8
+ api_key = nil
9
+ output_format = "json"
10
+
11
+ args = ARGV.dup
12
+ while args.any?
13
+ arg = args.shift
14
+ case arg
15
+ when "--api-key"
16
+ api_key = args.shift
17
+ when "--output-format"
18
+ output_format = args.shift
19
+ when "--help", "-h"
20
+ puts <<~HELP
21
+ Usage: exa-ai import-get <import_id> [OPTIONS]
22
+
23
+ Get details of a specific import
24
+
25
+ Arguments:
26
+ import_id ID of the import (required)
27
+
28
+ Options:
29
+ --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)
31
+ --help, -h Show this help message
32
+
33
+ Examples:
34
+ exa-ai import-get imp_123
35
+ exa-ai import-get imp_123 --output-format text
36
+ HELP
37
+ exit 0
38
+ else
39
+ # First positional argument is import_id
40
+ if import_id.nil?
41
+ import_id = arg
42
+ else
43
+ $stderr.puts "Unknown option: #{arg}"
44
+ exit 1
45
+ end
46
+ end
47
+ end
48
+
49
+ # Validate
50
+ if import_id.nil?
51
+ $stderr.puts "Error: import_id argument is required"
52
+ $stderr.puts "Usage: exa-ai import-get <import_id> [OPTIONS]"
53
+ $stderr.puts "Try 'exa-ai import-get --help' for more information"
54
+ exit 1
55
+ end
56
+
57
+ begin
58
+ # Resolve API key and format
59
+ api_key = Exa::CLI::Base.resolve_api_key(api_key)
60
+ output_format = Exa::CLI::Base.resolve_output_format(output_format)
61
+
62
+ # Build client
63
+ client = Exa::CLI::Base.build_client(api_key)
64
+
65
+ # Get import
66
+ import = client.get_import(import_id)
67
+
68
+ # Format and output
69
+ output = Exa::CLI::Formatters::ImportFormatter.format(import, output_format)
70
+ puts output
71
+
72
+ rescue Exa::NotFound => e
73
+ $stderr.puts "Import not found: #{e.message}"
74
+ exit 1
75
+ rescue Exa::Unauthorized => e
76
+ $stderr.puts "Authentication error: #{e.message}"
77
+ $stderr.puts "Check your API key (set EXA_API_KEY or use --api-key)"
78
+ exit 1
79
+ rescue Exa::ClientError => e
80
+ $stderr.puts "Client error: #{e.message}"
81
+ exit 1
82
+ rescue Exa::ServerError => e
83
+ $stderr.puts "Server error: #{e.message}"
84
+ exit 1
85
+ rescue Exa::Error => e
86
+ $stderr.puts "Error: #{e.message}"
87
+ exit 1
88
+ rescue StandardError => e
89
+ $stderr.puts "Unexpected error: #{e.message}"
90
+ $stderr.puts e.backtrace.first(5) if ENV["DEBUG"]
91
+ exit 1
92
+ end
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "exa-ai"
5
+
6
+ # Parse arguments
7
+ api_key = nil
8
+ output_format = "json"
9
+
10
+ args = ARGV.dup
11
+ while args.any?
12
+ arg = args.shift
13
+ case arg
14
+ when "--api-key"
15
+ api_key = args.shift
16
+ when "--output-format"
17
+ output_format = args.shift
18
+ when "--help", "-h"
19
+ puts <<~HELP
20
+ Usage: exa-ai import-list [OPTIONS]
21
+
22
+ List all imports
23
+
24
+ Options:
25
+ --api-key KEY Exa API key (or set EXA_API_KEY env var)
26
+ --output-format FMT Output format: json, pretty, or text (default: json)
27
+ --help, -h Show this help message
28
+
29
+ Examples:
30
+ exa-ai import-list
31
+ exa-ai import-list --output-format text
32
+ HELP
33
+ exit 0
34
+ else
35
+ $stderr.puts "Unknown option: #{arg}"
36
+ exit 1
37
+ end
38
+ end
39
+
40
+ begin
41
+ # Resolve API key and format
42
+ api_key = Exa::CLI::Base.resolve_api_key(api_key)
43
+ output_format = Exa::CLI::Base.resolve_output_format(output_format)
44
+
45
+ # Build client
46
+ client = Exa::CLI::Base.build_client(api_key)
47
+
48
+ # List imports
49
+ collection = client.list_imports
50
+
51
+ # Format and output
52
+ output = Exa::CLI::Formatters::ImportFormatter.format_collection(collection, output_format)
53
+ puts output
54
+
55
+ rescue Exa::Unauthorized => e
56
+ $stderr.puts "Authentication error: #{e.message}"
57
+ $stderr.puts "Check your API key (set EXA_API_KEY or use --api-key)"
58
+ exit 1
59
+ rescue Exa::ClientError => e
60
+ $stderr.puts "Client error: #{e.message}"
61
+ exit 1
62
+ rescue Exa::ServerError => e
63
+ $stderr.puts "Server error: #{e.message}"
64
+ exit 1
65
+ rescue Exa::Error => e
66
+ $stderr.puts "Error: #{e.message}"
67
+ exit 1
68
+ rescue StandardError => e
69
+ $stderr.puts "Unexpected error: #{e.message}"
70
+ $stderr.puts e.backtrace.first(5) if ENV["DEBUG"]
71
+ exit 1
72
+ end