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.
- checksums.yaml +4 -4
- data/README.md +10 -0
- data/exe/exa-ai +61 -7
- data/exe/exa-ai-answer +9 -8
- data/exe/exa-ai-context +6 -5
- data/exe/exa-ai-enrichment-cancel +1 -0
- data/exe/exa-ai-enrichment-create +1 -0
- data/exe/exa-ai-enrichment-delete +1 -0
- data/exe/exa-ai-enrichment-get +1 -0
- data/exe/exa-ai-enrichment-list +1 -0
- data/exe/exa-ai-enrichment-update +1 -0
- data/exe/exa-ai-find-similar +1 -0
- data/exe/exa-ai-get-contents +9 -8
- data/exe/exa-ai-import-create +235 -0
- data/exe/exa-ai-import-delete +92 -0
- data/exe/exa-ai-import-get +92 -0
- data/exe/exa-ai-import-list +72 -0
- data/exe/exa-ai-import-update +164 -0
- data/exe/exa-ai-monitor-create +223 -0
- data/exe/exa-ai-monitor-delete +101 -0
- data/exe/exa-ai-monitor-get +92 -0
- data/exe/exa-ai-monitor-list +90 -0
- data/exe/exa-ai-monitor-runs-get +103 -0
- data/exe/exa-ai-monitor-runs-list +110 -0
- data/exe/exa-ai-monitor-update +207 -0
- data/exe/exa-ai-research-get +7 -7
- data/exe/exa-ai-research-list +5 -5
- data/exe/exa-ai-research-start +8 -7
- data/exe/exa-ai-search +20 -13
- data/exe/exa-ai-webset-cancel +1 -0
- data/exe/exa-ai-webset-create +44 -6
- data/exe/exa-ai-webset-delete +1 -0
- data/exe/exa-ai-webset-get +1 -0
- data/exe/exa-ai-webset-item-get +1 -0
- data/exe/exa-ai-webset-item-list +1 -0
- data/exe/exa-ai-webset-list +1 -0
- data/exe/exa-ai-webset-search-cancel +1 -0
- data/exe/exa-ai-webset-search-create +1 -0
- data/exe/exa-ai-webset-search-get +1 -0
- data/exe/exa-ai-webset-update +1 -0
- data/lib/exa/cli/base.rb +8 -2
- data/lib/exa/cli/formatters/answer_formatter.rb +2 -0
- data/lib/exa/cli/formatters/contents_formatter.rb +2 -0
- data/lib/exa/cli/formatters/context_formatter.rb +2 -0
- data/lib/exa/cli/formatters/enrichment_formatter.rb +4 -0
- data/lib/exa/cli/formatters/import_formatter.rb +85 -0
- data/lib/exa/cli/formatters/monitor_formatter.rb +81 -0
- data/lib/exa/cli/formatters/monitor_run_formatter.rb +75 -0
- data/lib/exa/cli/formatters/research_formatter.rb +4 -0
- data/lib/exa/cli/formatters/search_formatter.rb +2 -0
- data/lib/exa/cli/formatters/webset_formatter.rb +4 -0
- data/lib/exa/cli/formatters/webset_item_formatter.rb +4 -0
- data/lib/exa/client.rb +137 -0
- data/lib/exa/constants/websets.rb +19 -0
- data/lib/exa/middleware/raise_error.rb +5 -0
- data/lib/exa/resources/import.rb +86 -0
- data/lib/exa/resources/import_collection.rb +33 -0
- data/lib/exa/resources/monitor.rb +48 -0
- data/lib/exa/resources/monitor_collection.rb +30 -0
- data/lib/exa/resources/monitor_run.rb +52 -0
- data/lib/exa/resources/monitor_run_collection.rb +30 -0
- data/lib/exa/services/search.rb +21 -1
- data/lib/exa/services/websets/create_validator.rb +5 -3
- data/lib/exa/services/websets/import_create.rb +40 -0
- data/lib/exa/services/websets/import_delete.rb +37 -0
- data/lib/exa/services/websets/import_get.rb +37 -0
- data/lib/exa/services/websets/import_list.rb +25 -0
- data/lib/exa/services/websets/import_update.rb +38 -0
- data/lib/exa/services/websets/import_upload.rb +58 -0
- data/lib/exa/services/websets/monitors/create.rb +42 -0
- data/lib/exa/services/websets/monitors/delete.rb +32 -0
- data/lib/exa/services/websets/monitors/get.rb +33 -0
- data/lib/exa/services/websets/monitors/list.rb +27 -0
- data/lib/exa/services/websets/monitors/runs/get.rb +37 -0
- data/lib/exa/services/websets/monitors/runs/list.rb +30 -0
- data/lib/exa/services/websets/monitors/update.rb +33 -0
- data/lib/exa/version.rb +1 -1
- data/lib/exa.rb +23 -0
- metadata +50 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "exa-ai"
|
|
5
|
+
|
|
6
|
+
# Parse arguments
|
|
7
|
+
monitor_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 monitor-get <monitor_id> [OPTIONS]
|
|
22
|
+
|
|
23
|
+
Retrieve details for a monitor
|
|
24
|
+
|
|
25
|
+
Arguments:
|
|
26
|
+
monitor_id ID of the monitor to retrieve (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 monitor-get mon_abc123
|
|
35
|
+
exa-ai monitor-get mon_abc123 --output-format pretty
|
|
36
|
+
HELP
|
|
37
|
+
exit 0
|
|
38
|
+
else
|
|
39
|
+
# First positional argument is monitor_id
|
|
40
|
+
if monitor_id.nil?
|
|
41
|
+
monitor_id = arg
|
|
42
|
+
else
|
|
43
|
+
$stderr.puts "Unknown option: #{arg}"
|
|
44
|
+
exit 1
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Validate
|
|
50
|
+
if monitor_id.nil?
|
|
51
|
+
$stderr.puts "Error: monitor_id argument is required"
|
|
52
|
+
$stderr.puts "Usage: exa-ai monitor-get <monitor_id> [OPTIONS]"
|
|
53
|
+
$stderr.puts "Try 'exa-ai monitor-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 monitor
|
|
66
|
+
monitor = client.get_monitor(monitor_id)
|
|
67
|
+
|
|
68
|
+
# Format and output
|
|
69
|
+
output = Exa::CLI::Formatters::MonitorFormatter.format(monitor, output_format)
|
|
70
|
+
puts output
|
|
71
|
+
|
|
72
|
+
rescue Exa::NotFound => e
|
|
73
|
+
$stderr.puts "Monitor 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,90 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "exa-ai"
|
|
5
|
+
|
|
6
|
+
# Parse arguments
|
|
7
|
+
limit = nil
|
|
8
|
+
cursor = 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 "--limit"
|
|
17
|
+
limit = args.shift&.to_i
|
|
18
|
+
when "--cursor"
|
|
19
|
+
cursor = args.shift
|
|
20
|
+
when "--api-key"
|
|
21
|
+
api_key = args.shift
|
|
22
|
+
when "--output-format"
|
|
23
|
+
output_format = args.shift
|
|
24
|
+
when "--help", "-h"
|
|
25
|
+
puts <<~HELP
|
|
26
|
+
Usage: exa-ai monitor-list [OPTIONS]
|
|
27
|
+
|
|
28
|
+
List all monitors with optional pagination
|
|
29
|
+
|
|
30
|
+
Options:
|
|
31
|
+
--limit N Maximum number of monitors to return (default: 25, max: 100)
|
|
32
|
+
--cursor CURSOR Cursor for pagination (use nextCursor from previous response)
|
|
33
|
+
--api-key KEY Exa API key (or set EXA_API_KEY env var)
|
|
34
|
+
--output-format FMT Output format: json, pretty, or text (default: json)
|
|
35
|
+
--help, -h Show this help message
|
|
36
|
+
|
|
37
|
+
Examples:
|
|
38
|
+
exa-ai monitor-list
|
|
39
|
+
exa-ai monitor-list --limit 10
|
|
40
|
+
exa-ai monitor-list --limit 5 --cursor "abc123"
|
|
41
|
+
exa-ai monitor-list --output-format pretty
|
|
42
|
+
HELP
|
|
43
|
+
exit 0
|
|
44
|
+
else
|
|
45
|
+
$stderr.puts "Unknown option: #{arg}"
|
|
46
|
+
exit 1
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
begin
|
|
51
|
+
# Resolve API key and format
|
|
52
|
+
api_key = Exa::CLI::Base.resolve_api_key(api_key)
|
|
53
|
+
output_format = Exa::CLI::Base.resolve_output_format(output_format)
|
|
54
|
+
|
|
55
|
+
# Build client
|
|
56
|
+
client = Exa::CLI::Base.build_client(api_key)
|
|
57
|
+
|
|
58
|
+
# List monitors with optional pagination
|
|
59
|
+
list_params = {}
|
|
60
|
+
list_params[:limit] = limit if limit
|
|
61
|
+
list_params[:cursor] = cursor if cursor
|
|
62
|
+
|
|
63
|
+
collection = client.list_monitors(**list_params)
|
|
64
|
+
|
|
65
|
+
# Format and output
|
|
66
|
+
output = Exa::CLI::Formatters::MonitorFormatter.format_collection(collection, output_format)
|
|
67
|
+
puts output
|
|
68
|
+
|
|
69
|
+
rescue Exa::ConfigurationError => e
|
|
70
|
+
$stderr.puts "Configuration error: #{e.message}"
|
|
71
|
+
exit 1
|
|
72
|
+
rescue Exa::Unauthorized => e
|
|
73
|
+
$stderr.puts "Authentication error: #{e.message}"
|
|
74
|
+
$stderr.puts "Check your API key (set EXA_API_KEY or use --api-key)"
|
|
75
|
+
exit 1
|
|
76
|
+
rescue Exa::ClientError => e
|
|
77
|
+
$stderr.puts "Client error: #{e.message}"
|
|
78
|
+
exit 1
|
|
79
|
+
rescue Exa::ServerError => e
|
|
80
|
+
$stderr.puts "Server error: #{e.message}"
|
|
81
|
+
$stderr.puts "The Exa API may be experiencing issues. Please try again later."
|
|
82
|
+
exit 1
|
|
83
|
+
rescue Exa::Error => e
|
|
84
|
+
$stderr.puts "Error: #{e.message}"
|
|
85
|
+
exit 1
|
|
86
|
+
rescue StandardError => e
|
|
87
|
+
$stderr.puts "Unexpected error: #{e.message}"
|
|
88
|
+
$stderr.puts e.backtrace.first(5) if ENV["DEBUG"]
|
|
89
|
+
exit 1
|
|
90
|
+
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
|
+
monitor_id = nil
|
|
8
|
+
run_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 monitor-runs-get <monitor_id> <run_id> [OPTIONS]
|
|
23
|
+
|
|
24
|
+
Retrieve details for a specific monitor run
|
|
25
|
+
|
|
26
|
+
Arguments:
|
|
27
|
+
monitor_id ID of the monitor (required)
|
|
28
|
+
run_id ID of the run 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 monitor-runs-get mon_abc123 run_xyz789
|
|
37
|
+
exa-ai monitor-runs-get mon_abc123 run_xyz789 --output-format pretty
|
|
38
|
+
HELP
|
|
39
|
+
exit 0
|
|
40
|
+
else
|
|
41
|
+
# First positional argument is monitor_id, second is run_id
|
|
42
|
+
if monitor_id.nil?
|
|
43
|
+
monitor_id = arg
|
|
44
|
+
elsif run_id.nil?
|
|
45
|
+
run_id = arg
|
|
46
|
+
else
|
|
47
|
+
$stderr.puts "Unknown option: #{arg}"
|
|
48
|
+
exit 1
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Validate
|
|
54
|
+
if monitor_id.nil?
|
|
55
|
+
$stderr.puts "Error: monitor_id argument is required"
|
|
56
|
+
$stderr.puts "Usage: exa-ai monitor-runs-get <monitor_id> <run_id> [OPTIONS]"
|
|
57
|
+
$stderr.puts "Try 'exa-ai monitor-runs-get --help' for more information"
|
|
58
|
+
exit 1
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if run_id.nil?
|
|
62
|
+
$stderr.puts "Error: run_id argument is required"
|
|
63
|
+
$stderr.puts "Usage: exa-ai monitor-runs-get <monitor_id> <run_id> [OPTIONS]"
|
|
64
|
+
$stderr.puts "Try 'exa-ai monitor-runs-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 monitor run
|
|
77
|
+
monitor_run = client.get_monitor_run(monitor_id: monitor_id, id: run_id)
|
|
78
|
+
|
|
79
|
+
# Format and output
|
|
80
|
+
output = Exa::CLI::Formatters::MonitorRunFormatter.format(monitor_run, output_format)
|
|
81
|
+
puts output
|
|
82
|
+
|
|
83
|
+
rescue Exa::NotFound => e
|
|
84
|
+
$stderr.puts "Monitor run 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,110 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "exa-ai"
|
|
5
|
+
|
|
6
|
+
# Parse arguments
|
|
7
|
+
monitor_id = nil
|
|
8
|
+
limit = nil
|
|
9
|
+
cursor = nil
|
|
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 "--limit"
|
|
18
|
+
limit = args.shift&.to_i
|
|
19
|
+
when "--cursor"
|
|
20
|
+
cursor = args.shift
|
|
21
|
+
when "--api-key"
|
|
22
|
+
api_key = args.shift
|
|
23
|
+
when "--output-format"
|
|
24
|
+
output_format = args.shift
|
|
25
|
+
when "--help", "-h"
|
|
26
|
+
puts <<~HELP
|
|
27
|
+
Usage: exa-ai monitor-runs-list <monitor_id> [OPTIONS]
|
|
28
|
+
|
|
29
|
+
List execution runs for a monitor
|
|
30
|
+
|
|
31
|
+
Arguments:
|
|
32
|
+
monitor_id ID of the monitor (required)
|
|
33
|
+
|
|
34
|
+
Options:
|
|
35
|
+
--limit N Maximum number of runs to return (default: 25, max: 100)
|
|
36
|
+
--cursor CURSOR Cursor for pagination (use nextCursor from previous response)
|
|
37
|
+
--api-key KEY Exa API key (or set EXA_API_KEY env var)
|
|
38
|
+
--output-format FMT Output format: json, pretty, or text (default: json)
|
|
39
|
+
--help, -h Show this help message
|
|
40
|
+
|
|
41
|
+
Examples:
|
|
42
|
+
exa-ai monitor-runs-list mon_abc123
|
|
43
|
+
exa-ai monitor-runs-list mon_abc123 --limit 10
|
|
44
|
+
exa-ai monitor-runs-list mon_abc123 --limit 5 --cursor "abc123"
|
|
45
|
+
exa-ai monitor-runs-list mon_abc123 --output-format pretty
|
|
46
|
+
HELP
|
|
47
|
+
exit 0
|
|
48
|
+
else
|
|
49
|
+
# First positional argument is monitor_id
|
|
50
|
+
if monitor_id.nil?
|
|
51
|
+
monitor_id = arg
|
|
52
|
+
else
|
|
53
|
+
$stderr.puts "Unknown option: #{arg}"
|
|
54
|
+
exit 1
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Validate
|
|
60
|
+
if monitor_id.nil?
|
|
61
|
+
$stderr.puts "Error: monitor_id argument is required"
|
|
62
|
+
$stderr.puts "Usage: exa-ai monitor-runs-list <monitor_id> [OPTIONS]"
|
|
63
|
+
$stderr.puts "Try 'exa-ai monitor-runs-list --help' for more information"
|
|
64
|
+
exit 1
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
begin
|
|
68
|
+
# Resolve API key and format
|
|
69
|
+
api_key = Exa::CLI::Base.resolve_api_key(api_key)
|
|
70
|
+
output_format = Exa::CLI::Base.resolve_output_format(output_format)
|
|
71
|
+
|
|
72
|
+
# Build client
|
|
73
|
+
client = Exa::CLI::Base.build_client(api_key)
|
|
74
|
+
|
|
75
|
+
# List monitor runs with optional pagination
|
|
76
|
+
list_params = {monitor_id: monitor_id}
|
|
77
|
+
list_params[:limit] = limit if limit
|
|
78
|
+
list_params[:cursor] = cursor if cursor
|
|
79
|
+
|
|
80
|
+
collection = client.list_monitor_runs(**list_params)
|
|
81
|
+
|
|
82
|
+
# Format and output
|
|
83
|
+
output = Exa::CLI::Formatters::MonitorRunFormatter.format_collection(collection, output_format)
|
|
84
|
+
puts output
|
|
85
|
+
|
|
86
|
+
rescue Exa::NotFound => e
|
|
87
|
+
$stderr.puts "Monitor not found: #{e.message}"
|
|
88
|
+
exit 1
|
|
89
|
+
rescue Exa::ConfigurationError => e
|
|
90
|
+
$stderr.puts "Configuration error: #{e.message}"
|
|
91
|
+
exit 1
|
|
92
|
+
rescue Exa::Unauthorized => e
|
|
93
|
+
$stderr.puts "Authentication error: #{e.message}"
|
|
94
|
+
$stderr.puts "Check your API key (set EXA_API_KEY or use --api-key)"
|
|
95
|
+
exit 1
|
|
96
|
+
rescue Exa::ClientError => e
|
|
97
|
+
$stderr.puts "Client error: #{e.message}"
|
|
98
|
+
exit 1
|
|
99
|
+
rescue Exa::ServerError => e
|
|
100
|
+
$stderr.puts "Server error: #{e.message}"
|
|
101
|
+
$stderr.puts "The Exa API may be experiencing issues. Please try again later."
|
|
102
|
+
exit 1
|
|
103
|
+
rescue Exa::Error => e
|
|
104
|
+
$stderr.puts "Error: #{e.message}"
|
|
105
|
+
exit 1
|
|
106
|
+
rescue StandardError => e
|
|
107
|
+
$stderr.puts "Unexpected error: #{e.message}"
|
|
108
|
+
$stderr.puts e.backtrace.first(5) if ENV["DEBUG"]
|
|
109
|
+
exit 1
|
|
110
|
+
end
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "exa-ai"
|
|
5
|
+
|
|
6
|
+
VALID_BEHAVIOR_TYPES = %w[search refresh].freeze
|
|
7
|
+
|
|
8
|
+
# Recursively convert hash keys from strings to symbols
|
|
9
|
+
def deep_symbolize_keys(obj)
|
|
10
|
+
case obj
|
|
11
|
+
when Hash
|
|
12
|
+
obj.each_with_object({}) do |(key, value), result|
|
|
13
|
+
result[key.to_sym] = deep_symbolize_keys(value)
|
|
14
|
+
end
|
|
15
|
+
when Array
|
|
16
|
+
obj.map { |item| deep_symbolize_keys(item) }
|
|
17
|
+
else
|
|
18
|
+
obj
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Parse JSON string or load from file (supports @file.json syntax)
|
|
23
|
+
def parse_json_or_file(value)
|
|
24
|
+
json_data = if value.start_with?("@")
|
|
25
|
+
file_path = value[1..]
|
|
26
|
+
JSON.parse(File.read(file_path))
|
|
27
|
+
else
|
|
28
|
+
JSON.parse(value)
|
|
29
|
+
end
|
|
30
|
+
deep_symbolize_keys(json_data)
|
|
31
|
+
rescue JSON::ParserError => e
|
|
32
|
+
$stderr.puts "Error: Invalid JSON: #{e.message}"
|
|
33
|
+
exit 1
|
|
34
|
+
rescue Errno::ENOENT => e
|
|
35
|
+
$stderr.puts "Error: File not found: #{e.message}"
|
|
36
|
+
exit 1
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Parse command-line arguments
|
|
40
|
+
def parse_args(argv)
|
|
41
|
+
# Check for help first
|
|
42
|
+
if argv.include?("--help") || argv.include?("-h")
|
|
43
|
+
puts <<~HELP
|
|
44
|
+
Usage: exa-ai monitor-update <monitor_id> [OPTIONS]
|
|
45
|
+
|
|
46
|
+
Update a monitor's schedule or behavior
|
|
47
|
+
|
|
48
|
+
Required:
|
|
49
|
+
<monitor_id> Monitor ID
|
|
50
|
+
|
|
51
|
+
Cadence options:
|
|
52
|
+
--cron EXPR Cron expression (e.g., "0 0 * * *")
|
|
53
|
+
--timezone TZ Timezone (e.g., "America/New_York")
|
|
54
|
+
|
|
55
|
+
Behavior options:
|
|
56
|
+
--behavior-type TYPE One of: #{VALID_BEHAVIOR_TYPES.join(', ')}
|
|
57
|
+
--query TEXT Search query (for search behavior)
|
|
58
|
+
--count N Number of results (for search behavior)
|
|
59
|
+
--behavior-mode MODE Mode: override or append (for search behavior)
|
|
60
|
+
|
|
61
|
+
Other options:
|
|
62
|
+
--api-key KEY Exa API key (or set EXA_API_KEY env var)
|
|
63
|
+
--output-format FMT Output format: json, pretty, or text (default: json)
|
|
64
|
+
--help, -h Show this help message
|
|
65
|
+
|
|
66
|
+
Examples:
|
|
67
|
+
# Update cron schedule
|
|
68
|
+
exa-ai monitor-update mon_123 --cron "0 */12 * * *"
|
|
69
|
+
|
|
70
|
+
# Update search query
|
|
71
|
+
exa-ai monitor-update mon_123 --query "AI startups in Europe"
|
|
72
|
+
|
|
73
|
+
# Update multiple fields
|
|
74
|
+
exa-ai monitor-update mon_123 --cron "0 0 * * *" --timezone "UTC" \\
|
|
75
|
+
--query "New companies" --count 100
|
|
76
|
+
HELP
|
|
77
|
+
exit 0
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
args = {
|
|
81
|
+
output_format: "json",
|
|
82
|
+
api_key: nil
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# First, check for positional argument (monitor_id)
|
|
86
|
+
if argv.empty? || argv[0].start_with?("--")
|
|
87
|
+
return args
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
args[:monitor_id] = argv[0]
|
|
91
|
+
i = 1
|
|
92
|
+
|
|
93
|
+
while i < argv.length
|
|
94
|
+
arg = argv[i]
|
|
95
|
+
case arg
|
|
96
|
+
when "--cron"
|
|
97
|
+
args[:cron] = argv[i + 1]
|
|
98
|
+
i += 2
|
|
99
|
+
when "--timezone"
|
|
100
|
+
args[:timezone] = argv[i + 1]
|
|
101
|
+
i += 2
|
|
102
|
+
when "--behavior-type"
|
|
103
|
+
args[:behavior_type] = argv[i + 1]
|
|
104
|
+
i += 2
|
|
105
|
+
when "--query"
|
|
106
|
+
args[:query] = argv[i + 1]
|
|
107
|
+
i += 2
|
|
108
|
+
when "--count"
|
|
109
|
+
args[:count] = argv[i + 1]&.to_i
|
|
110
|
+
i += 2
|
|
111
|
+
when "--behavior-mode"
|
|
112
|
+
args[:behavior_mode] = argv[i + 1]
|
|
113
|
+
i += 2
|
|
114
|
+
when "--api-key"
|
|
115
|
+
args[:api_key] = argv[i + 1]
|
|
116
|
+
i += 2
|
|
117
|
+
when "--output-format"
|
|
118
|
+
args[:output_format] = argv[i + 1]
|
|
119
|
+
i += 2
|
|
120
|
+
else
|
|
121
|
+
$stderr.puts "Unknown option: #{arg}"
|
|
122
|
+
exit 1
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
args
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Validate required arguments
|
|
130
|
+
def validate_args(args)
|
|
131
|
+
unless args[:monitor_id]
|
|
132
|
+
$stderr.puts "Error: monitor_id argument is required"
|
|
133
|
+
$stderr.puts "Usage: exa-ai monitor-update <monitor_id> [OPTIONS]"
|
|
134
|
+
$stderr.puts "Try 'exa-ai monitor-update --help' for more information"
|
|
135
|
+
exit 1
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Validate behavior type if provided
|
|
139
|
+
if args[:behavior_type] && !VALID_BEHAVIOR_TYPES.include?(args[:behavior_type])
|
|
140
|
+
$stderr.puts "Error: --behavior-type must be one of: #{VALID_BEHAVIOR_TYPES.join(', ')}"
|
|
141
|
+
exit 1
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Main execution
|
|
146
|
+
args = parse_args(ARGV)
|
|
147
|
+
validate_args(args)
|
|
148
|
+
|
|
149
|
+
begin
|
|
150
|
+
# Resolve API key and format
|
|
151
|
+
api_key = Exa::CLI::Base.resolve_api_key(args[:api_key])
|
|
152
|
+
output_format = Exa::CLI::Base.resolve_output_format(args[:output_format])
|
|
153
|
+
|
|
154
|
+
# Build client
|
|
155
|
+
client = Exa::CLI::Base.build_client(api_key)
|
|
156
|
+
|
|
157
|
+
# Build update params
|
|
158
|
+
update_params = {}
|
|
159
|
+
|
|
160
|
+
# Build cadence object if any cadence params provided
|
|
161
|
+
if args[:cron] || args[:timezone]
|
|
162
|
+
update_params[:cadence] = {}
|
|
163
|
+
update_params[:cadence][:cron] = args[:cron] if args[:cron]
|
|
164
|
+
update_params[:cadence][:timezone] = args[:timezone] if args[:timezone]
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Build behavior object if any behavior params provided
|
|
168
|
+
if args[:behavior_type] || args[:query] || args[:count] || args[:behavior_mode]
|
|
169
|
+
update_params[:behavior] = {}
|
|
170
|
+
update_params[:behavior][:type] = args[:behavior_type] if args[:behavior_type]
|
|
171
|
+
update_params[:behavior][:query] = args[:query] if args[:query]
|
|
172
|
+
update_params[:behavior][:count] = args[:count] if args[:count]
|
|
173
|
+
update_params[:behavior][:mode] = args[:behavior_mode] if args[:behavior_mode]
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Update monitor
|
|
177
|
+
monitor = client.update_monitor(args[:monitor_id], **update_params)
|
|
178
|
+
|
|
179
|
+
# Format and output
|
|
180
|
+
output = Exa::CLI::Formatters::MonitorFormatter.format(monitor, output_format)
|
|
181
|
+
puts output
|
|
182
|
+
|
|
183
|
+
rescue Exa::NotFound => e
|
|
184
|
+
$stderr.puts "Monitor not found: #{e.message}"
|
|
185
|
+
exit 1
|
|
186
|
+
rescue Exa::ConfigurationError => e
|
|
187
|
+
$stderr.puts "Configuration error: #{e.message}"
|
|
188
|
+
exit 1
|
|
189
|
+
rescue Exa::Unauthorized => e
|
|
190
|
+
$stderr.puts "Authentication error: #{e.message}"
|
|
191
|
+
$stderr.puts "Check your API key (set EXA_API_KEY or use --api-key)"
|
|
192
|
+
exit 1
|
|
193
|
+
rescue Exa::ClientError => e
|
|
194
|
+
$stderr.puts "Client error: #{e.message}"
|
|
195
|
+
exit 1
|
|
196
|
+
rescue Exa::ServerError => e
|
|
197
|
+
$stderr.puts "Server error: #{e.message}"
|
|
198
|
+
$stderr.puts "The Exa API may be experiencing issues. Please try again later."
|
|
199
|
+
exit 1
|
|
200
|
+
rescue Exa::Error => e
|
|
201
|
+
$stderr.puts "Error: #{e.message}"
|
|
202
|
+
exit 1
|
|
203
|
+
rescue StandardError => e
|
|
204
|
+
$stderr.puts "Unexpected error: #{e.message}"
|
|
205
|
+
$stderr.puts e.backtrace.first(5) if ENV["DEBUG"]
|
|
206
|
+
exit 1
|
|
207
|
+
end
|
data/exe/exa-ai-research-get
CHANGED
|
@@ -24,7 +24,7 @@ while args.any?
|
|
|
24
24
|
output_format = args.shift
|
|
25
25
|
when "--help", "-h"
|
|
26
26
|
puts <<~HELP
|
|
27
|
-
Usage: exa-
|
|
27
|
+
Usage: exa-ai research-get <research_id> [options]
|
|
28
28
|
|
|
29
29
|
Get the status and results of a research task.
|
|
30
30
|
|
|
@@ -39,10 +39,10 @@ while args.any?
|
|
|
39
39
|
--help, -h Show this help message
|
|
40
40
|
|
|
41
41
|
Examples:
|
|
42
|
-
exa-
|
|
43
|
-
exa-
|
|
44
|
-
exa-
|
|
45
|
-
exa-
|
|
42
|
+
exa-ai research-get research_123
|
|
43
|
+
exa-ai research-get research_123 --events
|
|
44
|
+
exa-ai research-get research_123 --stream
|
|
45
|
+
exa-ai research-get research_123 --output-format pretty
|
|
46
46
|
HELP
|
|
47
47
|
exit 0
|
|
48
48
|
else
|
|
@@ -59,8 +59,8 @@ end
|
|
|
59
59
|
# Validate required arguments
|
|
60
60
|
if research_id.nil?
|
|
61
61
|
warn "Error: Research ID argument required"
|
|
62
|
-
warn "Usage: exa-
|
|
63
|
-
warn "Try 'exa-
|
|
62
|
+
warn "Usage: exa-ai research-get <research_id> [options]"
|
|
63
|
+
warn "Try 'exa-ai research-get --help' for more information"
|
|
64
64
|
exit 1
|
|
65
65
|
end
|
|
66
66
|
|
data/exe/exa-ai-research-list
CHANGED
|
@@ -23,7 +23,7 @@ while args.any?
|
|
|
23
23
|
output_format = args.shift
|
|
24
24
|
when "--help", "-h"
|
|
25
25
|
puts <<~HELP
|
|
26
|
-
Usage: exa-
|
|
26
|
+
Usage: exa-ai research-list [options]
|
|
27
27
|
|
|
28
28
|
List research tasks with cursor-based pagination.
|
|
29
29
|
|
|
@@ -35,10 +35,10 @@ while args.any?
|
|
|
35
35
|
--help, -h Show this help message
|
|
36
36
|
|
|
37
37
|
Examples:
|
|
38
|
-
exa-
|
|
39
|
-
exa-
|
|
40
|
-
exa-
|
|
41
|
-
exa-
|
|
38
|
+
exa-ai research-list
|
|
39
|
+
exa-ai research-list --limit 20
|
|
40
|
+
exa-ai research-list --cursor next_page_cursor
|
|
41
|
+
exa-ai research-list --output-format pretty
|
|
42
42
|
HELP
|
|
43
43
|
exit 0
|
|
44
44
|
else
|