exa-ai 0.3.1 → 0.4.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +58 -17
  3. data/exe/exa-ai +111 -6
  4. data/exe/exa-ai-enrichment-cancel +107 -0
  5. data/exe/exa-ai-enrichment-create +235 -0
  6. data/exe/exa-ai-enrichment-delete +121 -0
  7. data/exe/exa-ai-enrichment-get +103 -0
  8. data/exe/exa-ai-enrichment-list +98 -0
  9. data/exe/exa-ai-enrichment-update +170 -0
  10. data/exe/exa-ai-find-similar +240 -0
  11. data/exe/exa-ai-webset-cancel +96 -0
  12. data/exe/exa-ai-webset-create +192 -0
  13. data/exe/exa-ai-webset-delete +110 -0
  14. data/exe/exa-ai-webset-get +92 -0
  15. data/exe/exa-ai-webset-item-delete +111 -0
  16. data/exe/exa-ai-webset-item-get +104 -0
  17. data/exe/exa-ai-webset-item-list +93 -0
  18. data/exe/exa-ai-webset-list +90 -0
  19. data/exe/exa-ai-webset-search-cancel +103 -0
  20. data/exe/exa-ai-webset-search-create +233 -0
  21. data/exe/exa-ai-webset-search-get +104 -0
  22. data/exe/exa-ai-webset-update +139 -0
  23. data/lib/exa/cli/formatters/enrichment_formatter.rb +69 -0
  24. data/lib/exa/cli/formatters/webset_formatter.rb +68 -0
  25. data/lib/exa/cli/formatters/webset_item_formatter.rb +69 -0
  26. data/lib/exa/client.rb +171 -0
  27. data/lib/exa/resources/webset.rb +74 -0
  28. data/lib/exa/resources/webset_collection.rb +33 -0
  29. data/lib/exa/resources/webset_enrichment.rb +71 -0
  30. data/lib/exa/resources/webset_enrichment_collection.rb +28 -0
  31. data/lib/exa/resources/webset_search.rb +112 -0
  32. data/lib/exa/services/parameter_converter.rb +1 -0
  33. data/lib/exa/services/websets/cancel.rb +36 -0
  34. data/lib/exa/services/websets/cancel_enrichment.rb +35 -0
  35. data/lib/exa/services/websets/cancel_search.rb +44 -0
  36. data/lib/exa/services/websets/create.rb +45 -0
  37. data/lib/exa/services/websets/create_enrichment.rb +35 -0
  38. data/lib/exa/services/websets/create_search.rb +48 -0
  39. data/lib/exa/services/websets/create_search_validator.rb +128 -0
  40. data/lib/exa/services/websets/create_validator.rb +189 -0
  41. data/lib/exa/services/websets/delete.rb +36 -0
  42. data/lib/exa/services/websets/delete_enrichment.rb +35 -0
  43. data/lib/exa/services/websets/delete_item.rb +20 -0
  44. data/lib/exa/services/websets/get_item.rb +20 -0
  45. data/lib/exa/services/websets/get_search.rb +43 -0
  46. data/lib/exa/services/websets/list.rb +25 -0
  47. data/lib/exa/services/websets/list_items.rb +20 -0
  48. data/lib/exa/services/websets/retrieve.rb +47 -0
  49. data/lib/exa/services/websets/retrieve_enrichment.rb +35 -0
  50. data/lib/exa/services/websets/update.rb +37 -0
  51. data/lib/exa/services/websets/update_enrichment.rb +36 -0
  52. data/lib/exa/services/websets_parameter_converter.rb +45 -0
  53. data/lib/exa/version.rb +1 -1
  54. data/lib/exa.rb +25 -0
  55. metadata +64 -3
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "exa-ai"
5
+
6
+ # Parse arguments
7
+ webset_id = nil
8
+ enrichment_id = nil
9
+ force = false
10
+ api_key = nil
11
+ output_format = "json"
12
+
13
+ args = ARGV.dup
14
+ while args.any?
15
+ arg = args.shift
16
+ case arg
17
+ when "--force"
18
+ force = true
19
+ when "--api-key"
20
+ api_key = args.shift
21
+ when "--output-format"
22
+ output_format = args.shift
23
+ when "--help", "-h"
24
+ puts <<~HELP
25
+ Usage: exa-ai enrichment-delete <webset_id> <enrichment_id> [OPTIONS]
26
+
27
+ Delete an enrichment
28
+
29
+ Arguments:
30
+ webset_id ID of the webset (required)
31
+ enrichment_id ID of the enrichment to delete (required)
32
+
33
+ Options:
34
+ --force Skip confirmation prompt
35
+ --api-key KEY Exa API key (or set EXA_API_KEY env var)
36
+ --output-format FMT Output format: json, pretty, or text (default: json)
37
+ --help, -h Show this help message
38
+
39
+ Examples:
40
+ exa-ai enrichment-delete ws_123 enr_456
41
+ exa-ai enrichment-delete ws_123 enr_456 --force
42
+ HELP
43
+ exit 0
44
+ else
45
+ # First positional argument is webset_id, second is enrichment_id
46
+ if webset_id.nil?
47
+ webset_id = arg
48
+ elsif enrichment_id.nil?
49
+ enrichment_id = arg
50
+ else
51
+ $stderr.puts "Unknown option: #{arg}"
52
+ exit 1
53
+ end
54
+ end
55
+ end
56
+
57
+ # Validate
58
+ if webset_id.nil?
59
+ $stderr.puts "Error: webset_id argument is required"
60
+ $stderr.puts "Usage: exa-ai enrichment-delete <webset_id> <enrichment_id> [OPTIONS]"
61
+ $stderr.puts "Try 'exa-ai enrichment-delete --help' for more information"
62
+ exit 1
63
+ end
64
+
65
+ if enrichment_id.nil?
66
+ $stderr.puts "Error: enrichment_id argument is required"
67
+ $stderr.puts "Usage: exa-ai enrichment-delete <webset_id> <enrichment_id> [OPTIONS]"
68
+ $stderr.puts "Try 'exa-ai enrichment-delete --help' for more information"
69
+ exit 1
70
+ end
71
+
72
+ begin
73
+ # Resolve API key and format
74
+ api_key = Exa::CLI::Base.resolve_api_key(api_key)
75
+ output_format = Exa::CLI::Base.resolve_output_format(output_format)
76
+
77
+ # Confirm deletion unless --force is used
78
+ unless force
79
+ $stderr.print "Delete enrichment #{enrichment_id} from webset #{webset_id}? (y/N): "
80
+ response = $stdin.gets.chomp.downcase
81
+ unless response == "y" || response == "yes"
82
+ $stderr.puts "Cancelled"
83
+ exit 0
84
+ end
85
+ end
86
+
87
+ # Build client
88
+ client = Exa::CLI::Base.build_client(api_key)
89
+
90
+ # Delete enrichment
91
+ result = client.delete_enrichment(webset_id: webset_id, id: enrichment_id)
92
+
93
+ # Format and output
94
+ output = Exa::CLI::Formatters::EnrichmentFormatter.format(result, output_format)
95
+ puts output
96
+
97
+ rescue Exa::NotFound => e
98
+ $stderr.puts "Enrichment not found: #{e.message}"
99
+ exit 1
100
+ rescue Exa::ConfigurationError => e
101
+ $stderr.puts "Configuration error: #{e.message}"
102
+ exit 1
103
+ rescue Exa::Unauthorized => e
104
+ $stderr.puts "Authentication error: #{e.message}"
105
+ $stderr.puts "Check your API key (set EXA_API_KEY or use --api-key)"
106
+ exit 1
107
+ rescue Exa::ClientError => e
108
+ $stderr.puts "Client error: #{e.message}"
109
+ exit 1
110
+ rescue Exa::ServerError => e
111
+ $stderr.puts "Server error: #{e.message}"
112
+ $stderr.puts "The Exa API may be experiencing issues. Please try again later."
113
+ exit 1
114
+ rescue Exa::Error => e
115
+ $stderr.puts "Error: #{e.message}"
116
+ exit 1
117
+ rescue StandardError => e
118
+ $stderr.puts "Unexpected error: #{e.message}"
119
+ $stderr.puts e.backtrace.first(5) if ENV["DEBUG"]
120
+ exit 1
121
+ end
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "exa-ai"
5
+
6
+ # Parse arguments
7
+ webset_id = nil
8
+ enrichment_id = nil
9
+ api_key = nil
10
+ output_format = "json"
11
+
12
+ args = ARGV.dup
13
+ while args.any?
14
+ arg = args.shift
15
+ case arg
16
+ when "--api-key"
17
+ api_key = args.shift
18
+ when "--output-format"
19
+ output_format = args.shift
20
+ when "--help", "-h"
21
+ puts <<~HELP
22
+ Usage: exa-ai enrichment-get <webset_id> <enrichment_id> [OPTIONS]
23
+
24
+ Retrieve details for an enrichment
25
+
26
+ Arguments:
27
+ webset_id ID of the webset (required)
28
+ enrichment_id ID of the enrichment to retrieve (required)
29
+
30
+ Options:
31
+ --api-key KEY Exa API key (or set EXA_API_KEY env var)
32
+ --output-format FMT Output format: json, pretty, or text (default: json)
33
+ --help, -h Show this help message
34
+
35
+ Examples:
36
+ exa-ai enrichment-get ws_123 enr_456
37
+ exa-ai enrichment-get ws_123 enr_456 --output-format pretty
38
+ HELP
39
+ exit 0
40
+ else
41
+ # First positional argument is webset_id, second is enrichment_id
42
+ if webset_id.nil?
43
+ webset_id = arg
44
+ elsif enrichment_id.nil?
45
+ enrichment_id = arg
46
+ else
47
+ $stderr.puts "Unknown option: #{arg}"
48
+ exit 1
49
+ end
50
+ end
51
+ end
52
+
53
+ # Validate
54
+ if webset_id.nil?
55
+ $stderr.puts "Error: webset_id argument is required"
56
+ $stderr.puts "Usage: exa-ai enrichment-get <webset_id> <enrichment_id> [OPTIONS]"
57
+ $stderr.puts "Try 'exa-ai enrichment-get --help' for more information"
58
+ exit 1
59
+ end
60
+
61
+ if enrichment_id.nil?
62
+ $stderr.puts "Error: enrichment_id argument is required"
63
+ $stderr.puts "Usage: exa-ai enrichment-get <webset_id> <enrichment_id> [OPTIONS]"
64
+ $stderr.puts "Try 'exa-ai enrichment-get --help' for more information"
65
+ exit 1
66
+ end
67
+
68
+ begin
69
+ # Resolve API key and format
70
+ api_key = Exa::CLI::Base.resolve_api_key(api_key)
71
+ output_format = Exa::CLI::Base.resolve_output_format(output_format)
72
+
73
+ # Build client
74
+ client = Exa::CLI::Base.build_client(api_key)
75
+
76
+ # Get enrichment
77
+ enrichment = client.get_enrichment(webset_id: webset_id, id: enrichment_id)
78
+
79
+ # Format and output
80
+ output = Exa::CLI::Formatters::EnrichmentFormatter.format(enrichment, output_format)
81
+ puts output
82
+
83
+ rescue Exa::NotFound => e
84
+ $stderr.puts "Enrichment not found: #{e.message}"
85
+ exit 1
86
+ rescue Exa::Unauthorized => e
87
+ $stderr.puts "Authentication error: #{e.message}"
88
+ $stderr.puts "Check your API key (set EXA_API_KEY or use --api-key)"
89
+ exit 1
90
+ rescue Exa::ClientError => e
91
+ $stderr.puts "Client error: #{e.message}"
92
+ exit 1
93
+ rescue Exa::ServerError => e
94
+ $stderr.puts "Server error: #{e.message}"
95
+ exit 1
96
+ rescue Exa::Error => e
97
+ $stderr.puts "Error: #{e.message}"
98
+ exit 1
99
+ rescue StandardError => e
100
+ $stderr.puts "Unexpected error: #{e.message}"
101
+ $stderr.puts e.backtrace.first(5) if ENV["DEBUG"]
102
+ exit 1
103
+ end
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "exa-ai"
5
+
6
+ # Parse arguments
7
+ webset_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 enrichment-list <webset_id> [OPTIONS]
22
+
23
+ List all enrichments for a webset
24
+
25
+ Arguments:
26
+ webset_id ID of the webset (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 enrichment-list ws_123
35
+ exa-ai enrichment-list ws_123 --output-format text
36
+ HELP
37
+ exit 0
38
+ else
39
+ # First positional argument is webset_id
40
+ if webset_id.nil?
41
+ webset_id = arg
42
+ else
43
+ $stderr.puts "Unknown option: #{arg}"
44
+ exit 1
45
+ end
46
+ end
47
+ end
48
+
49
+ # Validate
50
+ if webset_id.nil?
51
+ $stderr.puts "Error: webset_id argument is required"
52
+ $stderr.puts "Usage: exa-ai enrichment-list <webset_id> [OPTIONS]"
53
+ $stderr.puts "Try 'exa-ai enrichment-list --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 webset to retrieve enrichments
66
+ webset = client.get_webset(webset_id)
67
+
68
+ # Extract enrichments array (or empty array if none)
69
+ enrichments_data = webset.enrichments || []
70
+
71
+ # Create collection
72
+ collection = Exa::Resources::WebsetEnrichmentCollection.new(data: enrichments_data)
73
+
74
+ # Format and output
75
+ output = Exa::CLI::Formatters::EnrichmentFormatter.format_collection(collection, output_format)
76
+ puts output
77
+
78
+ rescue Exa::NotFound => e
79
+ $stderr.puts "Webset not found: #{e.message}"
80
+ exit 1
81
+ rescue Exa::Unauthorized => e
82
+ $stderr.puts "Authentication error: #{e.message}"
83
+ $stderr.puts "Check your API key (set EXA_API_KEY or use --api-key)"
84
+ exit 1
85
+ rescue Exa::ClientError => e
86
+ $stderr.puts "Client error: #{e.message}"
87
+ exit 1
88
+ rescue Exa::ServerError => e
89
+ $stderr.puts "Server error: #{e.message}"
90
+ exit 1
91
+ rescue Exa::Error => e
92
+ $stderr.puts "Error: #{e.message}"
93
+ exit 1
94
+ rescue StandardError => e
95
+ $stderr.puts "Unexpected error: #{e.message}"
96
+ $stderr.puts e.backtrace.first(5) if ENV["DEBUG"]
97
+ exit 1
98
+ end
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "exa-ai"
5
+ require "json"
6
+
7
+ # Recursively convert hash keys from strings to symbols
8
+ def deep_symbolize_keys(obj)
9
+ case obj
10
+ when Hash
11
+ obj.each_with_object({}) do |(key, value), result|
12
+ result[key.to_sym] = deep_symbolize_keys(value)
13
+ end
14
+ when Array
15
+ obj.map { |item| deep_symbolize_keys(item) }
16
+ else
17
+ obj
18
+ end
19
+ end
20
+
21
+ # Helper to parse JSON string or load from file
22
+ def parse_json_or_file(value)
23
+ json_data = if value.start_with?("@")
24
+ file_path = value[1..]
25
+ JSON.parse(File.read(file_path))
26
+ else
27
+ JSON.parse(value)
28
+ end
29
+ deep_symbolize_keys(json_data)
30
+ rescue JSON::ParserError => e
31
+ $stderr.puts "Error: Invalid JSON: #{e.message}"
32
+ exit 1
33
+ rescue Errno::ENOENT => e
34
+ $stderr.puts "Error: File not found: #{e.message}"
35
+ exit 1
36
+ end
37
+
38
+ # Parse arguments
39
+ webset_id = nil
40
+ enrichment_id = nil
41
+ description = nil
42
+ format = nil
43
+ options = nil
44
+ metadata = nil
45
+ api_key = nil
46
+ output_format = "json"
47
+
48
+ args = ARGV.dup
49
+ while args.any?
50
+ arg = args.shift
51
+ case arg
52
+ when "--description"
53
+ description = args.shift
54
+ when "--format"
55
+ format = args.shift
56
+ when "--options"
57
+ options = parse_json_or_file(args.shift)
58
+ when "--metadata"
59
+ metadata = parse_json_or_file(args.shift)
60
+ when "--api-key"
61
+ api_key = args.shift
62
+ when "--output-format"
63
+ output_format = args.shift
64
+ when "--help", "-h"
65
+ puts <<~HELP
66
+ Usage: exa-ai enrichment-update <webset_id> <enrichment_id> [OPTIONS]
67
+
68
+ Update an enrichment's properties
69
+
70
+ Arguments:
71
+ webset_id ID of the webset (required)
72
+ enrichment_id ID of the enrichment to update (required)
73
+
74
+ Options:
75
+ --description TEXT What to extract
76
+ --format TYPE One of: text, url, options
77
+ --options JSON Array of {label: "..."} (supports @file.json)
78
+ --metadata JSON Custom metadata (supports @file.json)
79
+ --api-key KEY Exa API key (or set EXA_API_KEY env var)
80
+ --output-format FMT Output format: json, pretty, or text (default: json)
81
+ --help, -h Show this help message
82
+
83
+ Examples:
84
+ exa-ai enrichment-update ws_123 enr_456 --description "New description"
85
+ exa-ai enrichment-update ws_123 enr_456 --metadata '{"priority":"high"}'
86
+ exa-ai enrichment-update ws_123 enr_456 --options options.json --format options
87
+ HELP
88
+ exit 0
89
+ else
90
+ # First positional argument is webset_id, second is enrichment_id
91
+ if webset_id.nil?
92
+ webset_id = arg
93
+ elsif enrichment_id.nil?
94
+ enrichment_id = arg
95
+ else
96
+ $stderr.puts "Unknown option: #{arg}"
97
+ exit 1
98
+ end
99
+ end
100
+ end
101
+
102
+ # Validate required arguments
103
+ if webset_id.nil?
104
+ $stderr.puts "Error: webset_id argument is required"
105
+ $stderr.puts "Usage: exa-ai enrichment-update <webset_id> <enrichment_id> [OPTIONS]"
106
+ $stderr.puts "Try 'exa-ai enrichment-update --help' for more information"
107
+ exit 1
108
+ end
109
+
110
+ if enrichment_id.nil?
111
+ $stderr.puts "Error: enrichment_id argument is required"
112
+ $stderr.puts "Usage: exa-ai enrichment-update <webset_id> <enrichment_id> [OPTIONS]"
113
+ $stderr.puts "Try 'exa-ai enrichment-update --help' for more information"
114
+ exit 1
115
+ end
116
+
117
+ # Check that at least one update field is provided
118
+ if description.nil? && format.nil? && options.nil? && metadata.nil?
119
+ $stderr.puts "Error: at least one update field is required (--description, --format, --options, or --metadata)"
120
+ $stderr.puts "Try 'exa-ai enrichment-update --help' for more information"
121
+ exit 1
122
+ end
123
+
124
+ begin
125
+ # Resolve API key and format
126
+ api_key = Exa::CLI::Base.resolve_api_key(api_key)
127
+ output_format = Exa::CLI::Base.resolve_output_format(output_format)
128
+
129
+ # Build client
130
+ client = Exa::CLI::Base.build_client(api_key)
131
+
132
+ # Build update params (only include provided fields)
133
+ update_params = {}
134
+ update_params[:description] = description if description
135
+ update_params[:format] = format if format
136
+ update_params[:options] = options if options
137
+ update_params[:metadata] = metadata if metadata
138
+
139
+ # Update enrichment
140
+ enrichment = client.update_enrichment(webset_id: webset_id, id: enrichment_id, **update_params)
141
+
142
+ # Format and output
143
+ output = Exa::CLI::Formatters::EnrichmentFormatter.format(enrichment, output_format)
144
+ puts output
145
+
146
+ rescue Exa::NotFound => e
147
+ $stderr.puts "Enrichment not found: #{e.message}"
148
+ exit 1
149
+ rescue Exa::ConfigurationError => e
150
+ $stderr.puts "Configuration error: #{e.message}"
151
+ exit 1
152
+ rescue Exa::Unauthorized => e
153
+ $stderr.puts "Authentication error: #{e.message}"
154
+ $stderr.puts "Check your API key (set EXA_API_KEY or use --api-key)"
155
+ exit 1
156
+ rescue Exa::ClientError => e
157
+ $stderr.puts "Client error: #{e.message}"
158
+ exit 1
159
+ rescue Exa::ServerError => e
160
+ $stderr.puts "Server error: #{e.message}"
161
+ $stderr.puts "The Exa API may be experiencing issues. Please try again later."
162
+ exit 1
163
+ rescue Exa::Error => e
164
+ $stderr.puts "Error: #{e.message}"
165
+ exit 1
166
+ rescue StandardError => e
167
+ $stderr.puts "Unexpected error: #{e.message}"
168
+ $stderr.puts e.backtrace.first(5) if ENV["DEBUG"]
169
+ exit 1
170
+ end