exa-ai 0.5.0 → 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 +55 -1
- 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-webset-create +43 -6
- 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/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/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,164 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "exa-ai"
|
|
5
|
+
|
|
6
|
+
# Recursively convert hash keys from strings to symbols
|
|
7
|
+
def deep_symbolize_keys(obj)
|
|
8
|
+
case obj
|
|
9
|
+
when Hash
|
|
10
|
+
obj.each_with_object({}) do |(key, value), result|
|
|
11
|
+
result[key.to_sym] = deep_symbolize_keys(value)
|
|
12
|
+
end
|
|
13
|
+
when Array
|
|
14
|
+
obj.map { |item| deep_symbolize_keys(item) }
|
|
15
|
+
else
|
|
16
|
+
obj
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Parse JSON string or load from file (supports @file.json syntax)
|
|
21
|
+
def parse_json_or_file(value)
|
|
22
|
+
json_data = if value.start_with?("@")
|
|
23
|
+
file_path = value[1..]
|
|
24
|
+
JSON.parse(File.read(file_path))
|
|
25
|
+
else
|
|
26
|
+
JSON.parse(value)
|
|
27
|
+
end
|
|
28
|
+
deep_symbolize_keys(json_data)
|
|
29
|
+
rescue JSON::ParserError => e
|
|
30
|
+
$stderr.puts "Error: Invalid JSON: #{e.message}"
|
|
31
|
+
exit 1
|
|
32
|
+
rescue Errno::ENOENT => e
|
|
33
|
+
$stderr.puts "Error: File not found: #{e.message}"
|
|
34
|
+
exit 1
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Parse command-line arguments
|
|
38
|
+
def parse_args(argv)
|
|
39
|
+
# Check for help first
|
|
40
|
+
if argv.include?("--help") || argv.include?("-h")
|
|
41
|
+
puts <<~HELP
|
|
42
|
+
Usage: exa-ai import-update <import_id> [OPTIONS]
|
|
43
|
+
|
|
44
|
+
Update an existing import
|
|
45
|
+
|
|
46
|
+
Required:
|
|
47
|
+
<import_id> Import ID
|
|
48
|
+
|
|
49
|
+
Options:
|
|
50
|
+
--title TEXT New display title
|
|
51
|
+
--metadata JSON New metadata (supports @file.json)
|
|
52
|
+
--api-key KEY Exa API key (or set EXA_API_KEY env var)
|
|
53
|
+
--output-format FMT Output format: json, pretty, or text (default: json)
|
|
54
|
+
--help, -h Show this help message
|
|
55
|
+
|
|
56
|
+
Examples:
|
|
57
|
+
exa-ai import-update imp_123 --title "Updated Title"
|
|
58
|
+
exa-ai import-update imp_123 --metadata '{"status":"reviewed"}'
|
|
59
|
+
exa-ai import-update imp_123 --title "New Title" --metadata @metadata.json
|
|
60
|
+
HELP
|
|
61
|
+
exit 0
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
args = {
|
|
65
|
+
output_format: "json",
|
|
66
|
+
api_key: nil
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
# First positional argument is import_id
|
|
70
|
+
if argv.empty? || argv[0].start_with?("--")
|
|
71
|
+
return args
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
args[:import_id] = argv[0]
|
|
75
|
+
i = 1
|
|
76
|
+
|
|
77
|
+
while i < argv.length
|
|
78
|
+
arg = argv[i]
|
|
79
|
+
case arg
|
|
80
|
+
when "--title"
|
|
81
|
+
args[:title] = argv[i + 1]
|
|
82
|
+
i += 2
|
|
83
|
+
when "--metadata"
|
|
84
|
+
args[:metadata] = parse_json_or_file(argv[i + 1])
|
|
85
|
+
i += 2
|
|
86
|
+
when "--api-key"
|
|
87
|
+
args[:api_key] = argv[i + 1]
|
|
88
|
+
i += 2
|
|
89
|
+
when "--output-format"
|
|
90
|
+
args[:output_format] = argv[i + 1]
|
|
91
|
+
i += 2
|
|
92
|
+
else
|
|
93
|
+
$stderr.puts "Unknown option: #{arg}"
|
|
94
|
+
exit 1
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
args
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Main execution
|
|
102
|
+
begin
|
|
103
|
+
args = parse_args(ARGV)
|
|
104
|
+
|
|
105
|
+
# Validate required parameters
|
|
106
|
+
unless args[:import_id]
|
|
107
|
+
$stderr.puts "Error: <import_id> is required"
|
|
108
|
+
$stderr.puts "Run 'exa-ai import-update --help' for usage information"
|
|
109
|
+
exit 1
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Validate at least one update parameter provided
|
|
113
|
+
unless args[:title] || args[:metadata]
|
|
114
|
+
$stderr.puts "Error: At least one of --title or --metadata must be provided"
|
|
115
|
+
$stderr.puts "Run 'exa-ai import-update --help' for usage information"
|
|
116
|
+
exit 1
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Resolve API key
|
|
120
|
+
api_key = Exa::CLI::Base.resolve_api_key(args[:api_key])
|
|
121
|
+
|
|
122
|
+
# Resolve output format
|
|
123
|
+
output_format = Exa::CLI::Base.resolve_output_format(args[:output_format])
|
|
124
|
+
|
|
125
|
+
# Build client
|
|
126
|
+
client = Exa::CLI::Base.build_client(api_key)
|
|
127
|
+
|
|
128
|
+
# Prepare update parameters (only include provided values)
|
|
129
|
+
update_params = {}
|
|
130
|
+
update_params[:title] = args[:title] if args[:title]
|
|
131
|
+
update_params[:metadata] = args[:metadata] if args[:metadata]
|
|
132
|
+
|
|
133
|
+
# Update import
|
|
134
|
+
import = client.update_import(args[:import_id], **update_params)
|
|
135
|
+
|
|
136
|
+
# Format and output result
|
|
137
|
+
output = Exa::CLI::Formatters::ImportFormatter.format(import, output_format)
|
|
138
|
+
puts output
|
|
139
|
+
|
|
140
|
+
rescue Exa::NotFound => e
|
|
141
|
+
$stderr.puts "Import not found: #{e.message}"
|
|
142
|
+
exit 1
|
|
143
|
+
rescue Exa::ConfigurationError => e
|
|
144
|
+
$stderr.puts "Configuration error: #{e.message}"
|
|
145
|
+
exit 1
|
|
146
|
+
rescue Exa::Unauthorized => e
|
|
147
|
+
$stderr.puts "Authentication error: #{e.message}"
|
|
148
|
+
$stderr.puts "Check your API key (set EXA_API_KEY or use --api-key)"
|
|
149
|
+
exit 1
|
|
150
|
+
rescue Exa::ClientError => e
|
|
151
|
+
$stderr.puts "Client error: #{e.message}"
|
|
152
|
+
exit 1
|
|
153
|
+
rescue Exa::ServerError => e
|
|
154
|
+
$stderr.puts "Server error: #{e.message}"
|
|
155
|
+
$stderr.puts "The Exa API may be experiencing issues. Please try again later."
|
|
156
|
+
exit 1
|
|
157
|
+
rescue Exa::Error => e
|
|
158
|
+
$stderr.puts "Error: #{e.message}"
|
|
159
|
+
exit 1
|
|
160
|
+
rescue StandardError => e
|
|
161
|
+
$stderr.puts "Unexpected error: #{e.message}"
|
|
162
|
+
$stderr.puts e.backtrace.first(5) if ENV["DEBUG"]
|
|
163
|
+
exit 1
|
|
164
|
+
end
|
|
@@ -0,0 +1,223 @@
|
|
|
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-create <webset_id> --cron EXPR --timezone TZ --behavior-type TYPE [OPTIONS]
|
|
45
|
+
|
|
46
|
+
Create a new monitor to automate webset updates on a schedule
|
|
47
|
+
|
|
48
|
+
Required:
|
|
49
|
+
<webset_id> Webset ID
|
|
50
|
+
--cron EXPR Cron expression (e.g., "0 0 * * *" for daily at midnight)
|
|
51
|
+
--timezone TZ Timezone (e.g., "America/New_York")
|
|
52
|
+
--behavior-type TYPE One of: #{VALID_BEHAVIOR_TYPES.join(', ')}
|
|
53
|
+
|
|
54
|
+
For search behavior:
|
|
55
|
+
--query TEXT Search query (required for search behavior)
|
|
56
|
+
--count N Number of results (optional)
|
|
57
|
+
--behavior-mode MODE Mode: override or append (optional, default: append)
|
|
58
|
+
|
|
59
|
+
Other options:
|
|
60
|
+
--api-key KEY Exa API key (or set EXA_API_KEY env var)
|
|
61
|
+
--output-format FMT Output format: json, pretty, or text (default: json)
|
|
62
|
+
--help, -h Show this help message
|
|
63
|
+
|
|
64
|
+
Examples:
|
|
65
|
+
# Create a search monitor
|
|
66
|
+
exa-ai monitor-create ws_123 --cron "0 0 * * *" --timezone "America/New_York" \\
|
|
67
|
+
--behavior-type search --query "AI startups in San Francisco" --count 50
|
|
68
|
+
|
|
69
|
+
# Create a refresh monitor
|
|
70
|
+
exa-ai monitor-create ws_123 --cron "0 */6 * * *" --timezone "UTC" \\
|
|
71
|
+
--behavior-type refresh
|
|
72
|
+
HELP
|
|
73
|
+
exit 0
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
args = {
|
|
77
|
+
output_format: "json",
|
|
78
|
+
api_key: nil
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# First, check for positional argument (webset_id)
|
|
82
|
+
if argv.empty? || argv[0].start_with?("--")
|
|
83
|
+
return args
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
args[:webset_id] = argv[0]
|
|
87
|
+
i = 1
|
|
88
|
+
|
|
89
|
+
while i < argv.length
|
|
90
|
+
arg = argv[i]
|
|
91
|
+
case arg
|
|
92
|
+
when "--cron"
|
|
93
|
+
args[:cron] = argv[i + 1]
|
|
94
|
+
i += 2
|
|
95
|
+
when "--timezone"
|
|
96
|
+
args[:timezone] = argv[i + 1]
|
|
97
|
+
i += 2
|
|
98
|
+
when "--behavior-type"
|
|
99
|
+
args[:behavior_type] = argv[i + 1]
|
|
100
|
+
i += 2
|
|
101
|
+
when "--query"
|
|
102
|
+
args[:query] = argv[i + 1]
|
|
103
|
+
i += 2
|
|
104
|
+
when "--count"
|
|
105
|
+
args[:count] = argv[i + 1]&.to_i
|
|
106
|
+
i += 2
|
|
107
|
+
when "--behavior-mode"
|
|
108
|
+
args[:behavior_mode] = argv[i + 1]
|
|
109
|
+
i += 2
|
|
110
|
+
when "--api-key"
|
|
111
|
+
args[:api_key] = argv[i + 1]
|
|
112
|
+
i += 2
|
|
113
|
+
when "--output-format"
|
|
114
|
+
args[:output_format] = argv[i + 1]
|
|
115
|
+
i += 2
|
|
116
|
+
else
|
|
117
|
+
$stderr.puts "Unknown option: #{arg}"
|
|
118
|
+
exit 1
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
args
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Validate required arguments
|
|
126
|
+
def validate_args(args)
|
|
127
|
+
unless args[:webset_id]
|
|
128
|
+
$stderr.puts "Error: webset_id argument is required"
|
|
129
|
+
$stderr.puts "Usage: exa-ai monitor-create <webset_id> --cron EXPR --timezone TZ --behavior-type TYPE [OPTIONS]"
|
|
130
|
+
$stderr.puts "Try 'exa-ai monitor-create --help' for more information"
|
|
131
|
+
exit 1
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
unless args[:cron]
|
|
135
|
+
$stderr.puts "Error: --cron is required"
|
|
136
|
+
$stderr.puts "Try 'exa-ai monitor-create --help' for more information"
|
|
137
|
+
exit 1
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
unless args[:timezone]
|
|
141
|
+
$stderr.puts "Error: --timezone is required"
|
|
142
|
+
$stderr.puts "Try 'exa-ai monitor-create --help' for more information"
|
|
143
|
+
exit 1
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
unless args[:behavior_type]
|
|
147
|
+
$stderr.puts "Error: --behavior-type is required"
|
|
148
|
+
$stderr.puts "Try 'exa-ai monitor-create --help' for more information"
|
|
149
|
+
exit 1
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
unless VALID_BEHAVIOR_TYPES.include?(args[:behavior_type])
|
|
153
|
+
$stderr.puts "Error: --behavior-type must be one of: #{VALID_BEHAVIOR_TYPES.join(', ')}"
|
|
154
|
+
exit 1
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Validate search behavior requirements
|
|
158
|
+
if args[:behavior_type] == "search" && !args[:query]
|
|
159
|
+
$stderr.puts "Error: --query is required for search behavior"
|
|
160
|
+
$stderr.puts "Try 'exa-ai monitor-create --help' for more information"
|
|
161
|
+
exit 1
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Main execution
|
|
166
|
+
args = parse_args(ARGV)
|
|
167
|
+
validate_args(args)
|
|
168
|
+
|
|
169
|
+
begin
|
|
170
|
+
# Resolve API key and format
|
|
171
|
+
api_key = Exa::CLI::Base.resolve_api_key(args[:api_key])
|
|
172
|
+
output_format = Exa::CLI::Base.resolve_output_format(args[:output_format])
|
|
173
|
+
|
|
174
|
+
# Build client
|
|
175
|
+
client = Exa::CLI::Base.build_client(api_key)
|
|
176
|
+
|
|
177
|
+
# Build cadence object
|
|
178
|
+
cadence = {
|
|
179
|
+
cron: args[:cron],
|
|
180
|
+
timezone: args[:timezone]
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
# Build behavior object
|
|
184
|
+
behavior = {type: args[:behavior_type]}
|
|
185
|
+
if args[:behavior_type] == "search"
|
|
186
|
+
behavior[:query] = args[:query]
|
|
187
|
+
behavior[:count] = args[:count] if args[:count]
|
|
188
|
+
behavior[:mode] = args[:behavior_mode] || "append"
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Create monitor
|
|
192
|
+
monitor = client.create_monitor(
|
|
193
|
+
webset_id: args[:webset_id],
|
|
194
|
+
cadence: cadence,
|
|
195
|
+
behavior: behavior
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
# Format and output
|
|
199
|
+
output = Exa::CLI::Formatters::MonitorFormatter.format(monitor, output_format)
|
|
200
|
+
puts output
|
|
201
|
+
|
|
202
|
+
rescue Exa::ConfigurationError => e
|
|
203
|
+
$stderr.puts "Configuration error: #{e.message}"
|
|
204
|
+
exit 1
|
|
205
|
+
rescue Exa::Unauthorized => e
|
|
206
|
+
$stderr.puts "Authentication error: #{e.message}"
|
|
207
|
+
$stderr.puts "Check your API key (set EXA_API_KEY or use --api-key)"
|
|
208
|
+
exit 1
|
|
209
|
+
rescue Exa::ClientError => e
|
|
210
|
+
$stderr.puts "Client error: #{e.message}"
|
|
211
|
+
exit 1
|
|
212
|
+
rescue Exa::ServerError => e
|
|
213
|
+
$stderr.puts "Server error: #{e.message}"
|
|
214
|
+
$stderr.puts "The Exa API may be experiencing issues. Please try again later."
|
|
215
|
+
exit 1
|
|
216
|
+
rescue Exa::Error => e
|
|
217
|
+
$stderr.puts "Error: #{e.message}"
|
|
218
|
+
exit 1
|
|
219
|
+
rescue StandardError => e
|
|
220
|
+
$stderr.puts "Unexpected error: #{e.message}"
|
|
221
|
+
$stderr.puts e.backtrace.first(5) if ENV["DEBUG"]
|
|
222
|
+
exit 1
|
|
223
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
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-delete <monitor_id> [OPTIONS]
|
|
22
|
+
|
|
23
|
+
Delete a monitor
|
|
24
|
+
|
|
25
|
+
Arguments:
|
|
26
|
+
monitor_id ID of the monitor 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 monitor-delete mon_abc123
|
|
35
|
+
exa-ai monitor-delete 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-delete <monitor_id> [OPTIONS]"
|
|
53
|
+
$stderr.puts "Try 'exa-ai monitor-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 monitor
|
|
66
|
+
result = client.delete_monitor(monitor_id)
|
|
67
|
+
|
|
68
|
+
# Format and output
|
|
69
|
+
output = case output_format
|
|
70
|
+
when "json"
|
|
71
|
+
JSON.generate(result)
|
|
72
|
+
when "pretty"
|
|
73
|
+
JSON.pretty_generate(result)
|
|
74
|
+
when "text"
|
|
75
|
+
"Monitor #{monitor_id} deleted successfully"
|
|
76
|
+
else
|
|
77
|
+
raise ArgumentError, "Unknown output format: #{output_format}"
|
|
78
|
+
end
|
|
79
|
+
puts output
|
|
80
|
+
|
|
81
|
+
rescue Exa::NotFound => e
|
|
82
|
+
$stderr.puts "Monitor not found: #{e.message}"
|
|
83
|
+
exit 1
|
|
84
|
+
rescue Exa::Unauthorized => e
|
|
85
|
+
$stderr.puts "Authentication error: #{e.message}"
|
|
86
|
+
$stderr.puts "Check your API key (set EXA_API_KEY or use --api-key)"
|
|
87
|
+
exit 1
|
|
88
|
+
rescue Exa::ClientError => e
|
|
89
|
+
$stderr.puts "Client error: #{e.message}"
|
|
90
|
+
exit 1
|
|
91
|
+
rescue Exa::ServerError => e
|
|
92
|
+
$stderr.puts "Server error: #{e.message}"
|
|
93
|
+
exit 1
|
|
94
|
+
rescue Exa::Error => e
|
|
95
|
+
$stderr.puts "Error: #{e.message}"
|
|
96
|
+
exit 1
|
|
97
|
+
rescue StandardError => e
|
|
98
|
+
$stderr.puts "Unexpected error: #{e.message}"
|
|
99
|
+
$stderr.puts e.backtrace.first(5) if ENV["DEBUG"]
|
|
100
|
+
exit 1
|
|
101
|
+
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
|
+
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
|