exa-ai 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -0
  3. data/exe/exa-ai +61 -7
  4. data/exe/exa-ai-answer +9 -8
  5. data/exe/exa-ai-context +6 -5
  6. data/exe/exa-ai-enrichment-cancel +1 -0
  7. data/exe/exa-ai-enrichment-create +1 -0
  8. data/exe/exa-ai-enrichment-delete +1 -0
  9. data/exe/exa-ai-enrichment-get +1 -0
  10. data/exe/exa-ai-enrichment-list +1 -0
  11. data/exe/exa-ai-enrichment-update +1 -0
  12. data/exe/exa-ai-find-similar +1 -0
  13. data/exe/exa-ai-get-contents +9 -8
  14. data/exe/exa-ai-import-create +235 -0
  15. data/exe/exa-ai-import-delete +92 -0
  16. data/exe/exa-ai-import-get +92 -0
  17. data/exe/exa-ai-import-list +72 -0
  18. data/exe/exa-ai-import-update +164 -0
  19. data/exe/exa-ai-monitor-create +223 -0
  20. data/exe/exa-ai-monitor-delete +101 -0
  21. data/exe/exa-ai-monitor-get +92 -0
  22. data/exe/exa-ai-monitor-list +90 -0
  23. data/exe/exa-ai-monitor-runs-get +103 -0
  24. data/exe/exa-ai-monitor-runs-list +110 -0
  25. data/exe/exa-ai-monitor-update +207 -0
  26. data/exe/exa-ai-research-get +7 -7
  27. data/exe/exa-ai-research-list +5 -5
  28. data/exe/exa-ai-research-start +8 -7
  29. data/exe/exa-ai-search +20 -13
  30. data/exe/exa-ai-webset-cancel +1 -0
  31. data/exe/exa-ai-webset-create +44 -6
  32. data/exe/exa-ai-webset-delete +1 -0
  33. data/exe/exa-ai-webset-get +1 -0
  34. data/exe/exa-ai-webset-item-get +1 -0
  35. data/exe/exa-ai-webset-item-list +1 -0
  36. data/exe/exa-ai-webset-list +1 -0
  37. data/exe/exa-ai-webset-search-cancel +1 -0
  38. data/exe/exa-ai-webset-search-create +1 -0
  39. data/exe/exa-ai-webset-search-get +1 -0
  40. data/exe/exa-ai-webset-update +1 -0
  41. data/lib/exa/cli/base.rb +8 -2
  42. data/lib/exa/cli/formatters/answer_formatter.rb +2 -0
  43. data/lib/exa/cli/formatters/contents_formatter.rb +2 -0
  44. data/lib/exa/cli/formatters/context_formatter.rb +2 -0
  45. data/lib/exa/cli/formatters/enrichment_formatter.rb +4 -0
  46. data/lib/exa/cli/formatters/import_formatter.rb +85 -0
  47. data/lib/exa/cli/formatters/monitor_formatter.rb +81 -0
  48. data/lib/exa/cli/formatters/monitor_run_formatter.rb +75 -0
  49. data/lib/exa/cli/formatters/research_formatter.rb +4 -0
  50. data/lib/exa/cli/formatters/search_formatter.rb +2 -0
  51. data/lib/exa/cli/formatters/webset_formatter.rb +4 -0
  52. data/lib/exa/cli/formatters/webset_item_formatter.rb +4 -0
  53. data/lib/exa/client.rb +137 -0
  54. data/lib/exa/constants/websets.rb +19 -0
  55. data/lib/exa/middleware/raise_error.rb +5 -0
  56. data/lib/exa/resources/import.rb +86 -0
  57. data/lib/exa/resources/import_collection.rb +33 -0
  58. data/lib/exa/resources/monitor.rb +48 -0
  59. data/lib/exa/resources/monitor_collection.rb +30 -0
  60. data/lib/exa/resources/monitor_run.rb +52 -0
  61. data/lib/exa/resources/monitor_run_collection.rb +30 -0
  62. data/lib/exa/services/search.rb +21 -1
  63. data/lib/exa/services/websets/create_validator.rb +5 -3
  64. data/lib/exa/services/websets/import_create.rb +40 -0
  65. data/lib/exa/services/websets/import_delete.rb +37 -0
  66. data/lib/exa/services/websets/import_get.rb +37 -0
  67. data/lib/exa/services/websets/import_list.rb +25 -0
  68. data/lib/exa/services/websets/import_update.rb +38 -0
  69. data/lib/exa/services/websets/import_upload.rb +58 -0
  70. data/lib/exa/services/websets/monitors/create.rb +42 -0
  71. data/lib/exa/services/websets/monitors/delete.rb +32 -0
  72. data/lib/exa/services/websets/monitors/get.rb +33 -0
  73. data/lib/exa/services/websets/monitors/list.rb +27 -0
  74. data/lib/exa/services/websets/monitors/runs/get.rb +37 -0
  75. data/lib/exa/services/websets/monitors/runs/list.rb +30 -0
  76. data/lib/exa/services/websets/monitors/update.rb +33 -0
  77. data/lib/exa/version.rb +1 -1
  78. data/lib/exa.rb +23 -0
  79. metadata +50 -1
@@ -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
@@ -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-api research-get <research_id> [options]
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-api research-get research_123
43
- exa-api research-get research_123 --events
44
- exa-api research-get research_123 --stream
45
- exa-api research-get research_123 --output-format pretty
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-api research-get <research_id> [options]"
63
- warn "Try 'exa-api research-get --help' for more information"
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
 
@@ -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-api research-list [options]
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-api research-list
39
- exa-api research-list --limit 20
40
- exa-api research-list --cursor next_page_cursor
41
- exa-api research-list --output-format pretty
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