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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -0
  3. data/exe/exa-ai +55 -1
  4. data/exe/exa-ai-import-create +235 -0
  5. data/exe/exa-ai-import-delete +92 -0
  6. data/exe/exa-ai-import-get +92 -0
  7. data/exe/exa-ai-import-list +72 -0
  8. data/exe/exa-ai-import-update +164 -0
  9. data/exe/exa-ai-monitor-create +223 -0
  10. data/exe/exa-ai-monitor-delete +101 -0
  11. data/exe/exa-ai-monitor-get +92 -0
  12. data/exe/exa-ai-monitor-list +90 -0
  13. data/exe/exa-ai-monitor-runs-get +103 -0
  14. data/exe/exa-ai-monitor-runs-list +110 -0
  15. data/exe/exa-ai-monitor-update +207 -0
  16. data/exe/exa-ai-webset-create +43 -6
  17. data/lib/exa/cli/base.rb +8 -2
  18. data/lib/exa/cli/formatters/answer_formatter.rb +2 -0
  19. data/lib/exa/cli/formatters/contents_formatter.rb +2 -0
  20. data/lib/exa/cli/formatters/context_formatter.rb +2 -0
  21. data/lib/exa/cli/formatters/enrichment_formatter.rb +4 -0
  22. data/lib/exa/cli/formatters/import_formatter.rb +85 -0
  23. data/lib/exa/cli/formatters/monitor_formatter.rb +81 -0
  24. data/lib/exa/cli/formatters/monitor_run_formatter.rb +75 -0
  25. data/lib/exa/cli/formatters/research_formatter.rb +4 -0
  26. data/lib/exa/cli/formatters/search_formatter.rb +2 -0
  27. data/lib/exa/cli/formatters/webset_formatter.rb +4 -0
  28. data/lib/exa/cli/formatters/webset_item_formatter.rb +4 -0
  29. data/lib/exa/client.rb +137 -0
  30. data/lib/exa/constants/websets.rb +19 -0
  31. data/lib/exa/resources/import.rb +86 -0
  32. data/lib/exa/resources/import_collection.rb +33 -0
  33. data/lib/exa/resources/monitor.rb +48 -0
  34. data/lib/exa/resources/monitor_collection.rb +30 -0
  35. data/lib/exa/resources/monitor_run.rb +52 -0
  36. data/lib/exa/resources/monitor_run_collection.rb +30 -0
  37. data/lib/exa/services/websets/create_validator.rb +5 -3
  38. data/lib/exa/services/websets/import_create.rb +40 -0
  39. data/lib/exa/services/websets/import_delete.rb +37 -0
  40. data/lib/exa/services/websets/import_get.rb +37 -0
  41. data/lib/exa/services/websets/import_list.rb +25 -0
  42. data/lib/exa/services/websets/import_update.rb +38 -0
  43. data/lib/exa/services/websets/import_upload.rb +58 -0
  44. data/lib/exa/services/websets/monitors/create.rb +42 -0
  45. data/lib/exa/services/websets/monitors/delete.rb +32 -0
  46. data/lib/exa/services/websets/monitors/get.rb +33 -0
  47. data/lib/exa/services/websets/monitors/list.rb +27 -0
  48. data/lib/exa/services/websets/monitors/runs/get.rb +37 -0
  49. data/lib/exa/services/websets/monitors/runs/list.rb +30 -0
  50. data/lib/exa/services/websets/monitors/update.rb +33 -0
  51. data/lib/exa/version.rb +1 -1
  52. data/lib/exa.rb +23 -0
  53. metadata +50 -1
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exa
4
+ module CLI
5
+ module Formatters
6
+ class MonitorFormatter
7
+ def self.format(monitor, output_format)
8
+ case output_format
9
+ when "json"
10
+ JSON.generate(monitor.to_h)
11
+ when "pretty"
12
+ JSON.pretty_generate(monitor.to_h)
13
+ when "text"
14
+ format_as_text(monitor)
15
+ when "toon"
16
+ Exa::CLI::Base.encode_as_toon(monitor.to_h)
17
+ else
18
+ raise ArgumentError, "Unknown output format: #{output_format}"
19
+ end
20
+ end
21
+
22
+ def self.format_collection(collection, output_format)
23
+ case output_format
24
+ when "json"
25
+ JSON.generate(collection.to_h)
26
+ when "pretty"
27
+ JSON.pretty_generate(collection.to_h)
28
+ when "text"
29
+ format_collection_as_text(collection)
30
+ when "toon"
31
+ Exa::CLI::Base.encode_as_toon(collection.to_h)
32
+ else
33
+ raise ArgumentError, "Unknown output format: #{output_format}"
34
+ end
35
+ end
36
+
37
+ def self.format_as_text(monitor)
38
+ lines = []
39
+ lines << "Monitor: #{monitor.id}"
40
+ lines << "Webset: #{monitor.webset_id}" if monitor.webset_id
41
+ lines << "Status: #{monitor.status}"
42
+
43
+ if monitor.cadence
44
+ lines << "\nCadence:"
45
+ lines << " Cron: #{monitor.cadence['cron']}" if monitor.cadence['cron']
46
+ lines << " Timezone: #{monitor.cadence['timezone']}" if monitor.cadence['timezone']
47
+ end
48
+
49
+ if monitor.behavior
50
+ lines << "\nBehavior:"
51
+ lines << " Type: #{monitor.behavior['type']}" if monitor.behavior['type']
52
+ lines << " Query: #{monitor.behavior['query']}" if monitor.behavior['query']
53
+ lines << " Count: #{monitor.behavior['count']}" if monitor.behavior['count']
54
+ end
55
+
56
+ lines << "\nCreated: #{monitor.created_at}" if monitor.created_at
57
+ lines << "Updated: #{monitor.updated_at}" if monitor.updated_at
58
+
59
+ lines.join("\n")
60
+ end
61
+ private_class_method :format_as_text
62
+
63
+ def self.format_collection_as_text(collection)
64
+ lines = ["Monitors (#{collection.data.length} items):"]
65
+ collection.data.each do |mon|
66
+ lines << "\n #{mon['id']}"
67
+ lines << " Status: #{mon['status']}"
68
+ lines << " Webset: #{mon['websetId']}" if mon['websetId']
69
+ end
70
+
71
+ if collection.has_more
72
+ lines << "\nMore available (cursor: #{collection.next_cursor})"
73
+ end
74
+
75
+ lines.join("\n")
76
+ end
77
+ private_class_method :format_collection_as_text
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exa
4
+ module CLI
5
+ module Formatters
6
+ class MonitorRunFormatter
7
+ def self.format(monitor_run, output_format)
8
+ case output_format
9
+ when "json"
10
+ JSON.generate(monitor_run.to_h)
11
+ when "pretty"
12
+ JSON.pretty_generate(monitor_run.to_h)
13
+ when "text"
14
+ format_as_text(monitor_run)
15
+ when "toon"
16
+ Exa::CLI::Base.encode_as_toon(monitor_run.to_h)
17
+ else
18
+ raise ArgumentError, "Unknown output format: #{output_format}"
19
+ end
20
+ end
21
+
22
+ def self.format_collection(collection, output_format)
23
+ case output_format
24
+ when "json"
25
+ JSON.generate(collection.to_h)
26
+ when "pretty"
27
+ JSON.pretty_generate(collection.to_h)
28
+ when "text"
29
+ format_collection_as_text(collection)
30
+ when "toon"
31
+ Exa::CLI::Base.encode_as_toon(collection.to_h)
32
+ else
33
+ raise ArgumentError, "Unknown output format: #{output_format}"
34
+ end
35
+ end
36
+
37
+ def self.format_as_text(monitor_run)
38
+ lines = []
39
+ lines << "Monitor Run: #{monitor_run.id}"
40
+ lines << "Monitor: #{monitor_run.monitor_id}" if monitor_run.monitor_id
41
+ lines << "Status: #{monitor_run.status}"
42
+
43
+ lines << "\nCreated: #{monitor_run.created_at}" if monitor_run.created_at
44
+ lines << "Updated: #{monitor_run.updated_at}" if monitor_run.updated_at
45
+ lines << "Completed: #{monitor_run.completed_at}" if monitor_run.completed_at
46
+
47
+ if monitor_run.failed?
48
+ lines << "Failed: #{monitor_run.failed_at}" if monitor_run.failed_at
49
+ lines << "Reason: #{monitor_run.failed_reason}" if monitor_run.failed_reason
50
+ end
51
+
52
+ lines.join("\n")
53
+ end
54
+ private_class_method :format_as_text
55
+
56
+ def self.format_collection_as_text(collection)
57
+ lines = ["Monitor Runs (#{collection.data.length} items):"]
58
+ collection.data.each do |run|
59
+ lines << "\n #{run['id']}"
60
+ lines << " Status: #{run['status']}"
61
+ lines << " Completed: #{run['completedAt']}" if run['completedAt']
62
+ lines << " Failed: #{run['failedReason']}" if run['failedReason']
63
+ end
64
+
65
+ if collection.has_more
66
+ lines << "\nMore available (cursor: #{collection.next_cursor})"
67
+ end
68
+
69
+ lines.join("\n")
70
+ end
71
+ private_class_method :format_collection_as_text
72
+ end
73
+ end
74
+ end
75
+ end
@@ -10,6 +10,8 @@ module Exa
10
10
  format_task_pretty(task, show_events: show_events)
11
11
  when "text"
12
12
  format_task_text(task, show_events: show_events)
13
+ when "toon"
14
+ Exa::CLI::Base.encode_as_toon(task.to_h)
13
15
  else
14
16
  JSON.pretty_generate(task.to_h)
15
17
  end
@@ -23,6 +25,8 @@ module Exa
23
25
  format_list_pretty(list)
24
26
  when "text"
25
27
  format_list_text(list)
28
+ when "toon"
29
+ Exa::CLI::Base.encode_as_toon(list.to_h)
26
30
  else
27
31
  JSON.pretty_generate(list.to_h)
28
32
  end
@@ -12,6 +12,8 @@ module Exa
12
12
  format_pretty(result)
13
13
  when "text"
14
14
  format_text(result)
15
+ when "toon"
16
+ Exa::CLI::Base.encode_as_toon(result.to_h)
15
17
  else
16
18
  JSON.pretty_generate(result.to_h)
17
19
  end
@@ -12,6 +12,8 @@ module Exa
12
12
  JSON.pretty_generate(webset.to_h)
13
13
  when "text"
14
14
  format_as_text(webset)
15
+ when "toon"
16
+ Exa::CLI::Base.encode_as_toon(webset.to_h)
15
17
  else
16
18
  raise ArgumentError, "Unknown output format: #{output_format}"
17
19
  end
@@ -25,6 +27,8 @@ module Exa
25
27
  JSON.pretty_generate(collection.to_h)
26
28
  when "text"
27
29
  format_collection_as_text(collection)
30
+ when "toon"
31
+ Exa::CLI::Base.encode_as_toon(collection.to_h)
28
32
  else
29
33
  raise ArgumentError, "Unknown output format: #{output_format}"
30
34
  end
@@ -12,6 +12,8 @@ module Exa
12
12
  JSON.pretty_generate(item)
13
13
  when "text"
14
14
  format_as_text(item)
15
+ when "toon"
16
+ Exa::CLI::Base.encode_as_toon(item)
15
17
  else
16
18
  raise ArgumentError, "Unknown output format: #{output_format}"
17
19
  end
@@ -25,6 +27,8 @@ module Exa
25
27
  JSON.pretty_generate(items)
26
28
  when "text"
27
29
  format_collection_as_text(items)
30
+ when "toon"
31
+ Exa::CLI::Base.encode_as_toon(items)
28
32
  else
29
33
  raise ArgumentError, "Unknown output format: #{output_format}"
30
34
  end
data/lib/exa/client.rb CHANGED
@@ -319,6 +319,143 @@ module Exa
319
319
  Services::Websets::ListItems.new(connection, webset_id: webset_id).call
320
320
  end
321
321
 
322
+ # List all imports
323
+ #
324
+ # @param params [Hash] Pagination parameters
325
+ # @option params [String] :cursor Cursor for pagination
326
+ # @option params [Integer] :limit Maximum number of imports to return
327
+ # @return [Resources::ImportCollection] Paginated list of imports
328
+ def list_imports(**params)
329
+ Services::Websets::ListImports.new(connection, **params).call
330
+ end
331
+
332
+ # Create a new import
333
+ #
334
+ # @param params [Hash] Import parameters
335
+ # @option params [Integer] :size Size of the import file
336
+ # @option params [Integer] :count Number of items to import
337
+ # @option params [String] :title Import title
338
+ # @option params [String] :format Import format (e.g., "csv")
339
+ # @option params [Hash] :entity Entity type specification
340
+ # @option params [Hash] :metadata Custom metadata
341
+ # @option params [Hash] :csv CSV-specific configuration
342
+ # @return [Resources::Import] The newly created import
343
+ def create_import(**params)
344
+ Services::Websets::CreateImport.new(connection, **params).call
345
+ end
346
+
347
+ # Upload a file for import (creates import and uploads file)
348
+ #
349
+ # @param file_path [String] Path to the file to upload
350
+ # @param params [Hash] Import parameters
351
+ # @option params [Integer] :count Number of items to import
352
+ # @option params [String] :title Import title
353
+ # @option params [String] :format Import format (e.g., "csv")
354
+ # @option params [Hash] :entity Entity type specification
355
+ # @option params [Hash] :metadata Custom metadata
356
+ # @option params [Hash] :csv CSV-specific configuration
357
+ # @return [Resources::Import] The created import (file size is inferred automatically)
358
+ def upload_import(file_path:, **params)
359
+ Services::Websets::UploadImport.new(connection, file_path: file_path, **params).call
360
+ end
361
+
362
+ # Get a specific import by ID
363
+ #
364
+ # @param id [String] Import ID
365
+ # @return [Resources::Import] The requested import
366
+ def get_import(id)
367
+ Services::Websets::GetImport.new(connection, id: id).call
368
+ end
369
+
370
+ # Update an import
371
+ #
372
+ # @param id [String] Import ID
373
+ # @param params [Hash] Update parameters
374
+ # @option params [String] :title Updated title
375
+ # @option params [Hash] :metadata Updated metadata
376
+ # @return [Resources::Import] The updated import
377
+ def update_import(id, **params)
378
+ Services::Websets::UpdateImport.new(connection, id: id, **params).call
379
+ end
380
+
381
+ # Delete an import
382
+ #
383
+ # @param id [String] Import ID
384
+ # @return [Resources::Import] The deleted import
385
+ def delete_import(id)
386
+ Services::Websets::DeleteImport.new(connection, id: id).call
387
+ end
388
+
389
+ # Create a new monitor for a webset
390
+ #
391
+ # @param webset_id [String] Webset ID
392
+ # @param cadence [Hash] Schedule configuration with :cron and :timezone
393
+ # @param behavior [Hash] Behavior configuration (type, query, etc.)
394
+ # @param params [Hash] Additional monitor parameters
395
+ # @option params [Hash] :metadata Custom metadata
396
+ # @return [Resources::Monitor] The newly created monitor
397
+ def create_monitor(webset_id:, cadence:, behavior:, **params)
398
+ Services::Websets::Monitors::Create.new(connection, webset_id: webset_id, cadence: cadence, behavior: behavior, **params).call
399
+ end
400
+
401
+ # List all monitors
402
+ #
403
+ # @param params [Hash] Pagination parameters
404
+ # @option params [String] :cursor Cursor for pagination
405
+ # @option params [Integer] :limit Maximum number of monitors to return
406
+ # @return [Resources::MonitorCollection] Paginated list of monitors
407
+ def list_monitors(**params)
408
+ Services::Websets::Monitors::List.new(connection, **params).call
409
+ end
410
+
411
+ # Get a specific monitor by ID
412
+ #
413
+ # @param id [String] Monitor ID
414
+ # @return [Resources::Monitor] The requested monitor
415
+ def get_monitor(id:)
416
+ Services::Websets::Monitors::Get.new(connection, id: id).call
417
+ end
418
+
419
+ # Update a monitor
420
+ #
421
+ # @param id [String] Monitor ID
422
+ # @param params [Hash] Update parameters
423
+ # @option params [Hash] :cadence Updated schedule configuration
424
+ # @option params [Hash] :behavior Updated behavior configuration
425
+ # @option params [Hash] :metadata Updated metadata
426
+ # @return [Resources::Monitor] The updated monitor
427
+ def update_monitor(id:, **params)
428
+ Services::Websets::Monitors::Update.new(connection, id: id, **params).call
429
+ end
430
+
431
+ # Delete a monitor
432
+ #
433
+ # @param id [String] Monitor ID
434
+ # @return [Resources::Monitor] The deleted monitor
435
+ def delete_monitor(id:)
436
+ Services::Websets::Monitors::Delete.new(connection, id: id).call
437
+ end
438
+
439
+ # List all runs for a specific monitor
440
+ #
441
+ # @param monitor_id [String] Monitor ID
442
+ # @param params [Hash] Pagination parameters
443
+ # @option params [String] :cursor Cursor for pagination
444
+ # @option params [Integer] :limit Maximum number of runs to return
445
+ # @return [Resources::MonitorRunCollection] Paginated list of monitor runs
446
+ def list_monitor_runs(monitor_id:, **params)
447
+ Services::Websets::Monitors::Runs::List.new(connection, monitor_id: monitor_id, **params).call
448
+ end
449
+
450
+ # Get a specific monitor run by ID
451
+ #
452
+ # @param monitor_id [String] Monitor ID
453
+ # @param id [String] Run ID
454
+ # @return [Resources::MonitorRun] The requested monitor run
455
+ def get_monitor_run(monitor_id:, id:)
456
+ Services::Websets::Monitors::Runs::Get.new(connection, monitor_id: monitor_id, id: id).call
457
+ end
458
+
322
459
  private
323
460
 
324
461
  def connection
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exa
4
+ module Constants
5
+ module Websets
6
+ # Valid entity types for websets
7
+ ENTITY_TYPES = %w[company person article research_paper custom].freeze
8
+
9
+ # Valid enrichment formats
10
+ ENRICHMENT_FORMATS = %w[text date number options url].freeze
11
+
12
+ # Valid source types for imports and exclusions
13
+ SOURCE_TYPES = %w[import webset].freeze
14
+
15
+ # Valid import formats
16
+ IMPORT_FORMATS = %w[csv].freeze
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exa
4
+ module Resources
5
+ # Represents an import operation for bringing external data into Exa
6
+ #
7
+ # An import allows uploading CSV data containing entities (e.g., companies)
8
+ # to be processed and enriched within the Exa system.
9
+ class Import < Struct.new(
10
+ :id,
11
+ :object,
12
+ :status,
13
+ :format,
14
+ :entity,
15
+ :title,
16
+ :count,
17
+ :metadata,
18
+ :failed_reason,
19
+ :failed_at,
20
+ :failed_message,
21
+ :created_at,
22
+ :updated_at,
23
+ :upload_url,
24
+ :upload_valid_until,
25
+ keyword_init: true
26
+ )
27
+ def initialize(
28
+ id:,
29
+ object:,
30
+ status:,
31
+ format: nil,
32
+ entity: nil,
33
+ title: nil,
34
+ count: nil,
35
+ metadata: nil,
36
+ failed_reason: nil,
37
+ failed_at: nil,
38
+ failed_message: nil,
39
+ created_at: nil,
40
+ updated_at: nil,
41
+ upload_url: nil,
42
+ upload_valid_until: nil
43
+ )
44
+ super
45
+ freeze
46
+ end
47
+
48
+ # Status helper methods
49
+ def pending?
50
+ status == "pending"
51
+ end
52
+
53
+ def processing?
54
+ status == "processing"
55
+ end
56
+
57
+ def completed?
58
+ status == "completed"
59
+ end
60
+
61
+ def failed?
62
+ status == "failed"
63
+ end
64
+
65
+ def to_h
66
+ {
67
+ id: id,
68
+ object: object,
69
+ status: status,
70
+ format: format,
71
+ entity: entity,
72
+ title: title,
73
+ count: count,
74
+ metadata: metadata,
75
+ failed_reason: failed_reason,
76
+ failed_at: failed_at,
77
+ failed_message: failed_message,
78
+ created_at: created_at,
79
+ updated_at: updated_at,
80
+ upload_url: upload_url,
81
+ upload_valid_until: upload_valid_until
82
+ }.compact
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exa
4
+ module Resources
5
+ # Represents a paginated list of imports from the Exa API
6
+ #
7
+ # This class wraps the JSON response from the GET /websets/v0/imports endpoint
8
+ # and provides pagination support.
9
+ class ImportCollection < Struct.new(
10
+ :data,
11
+ :has_more,
12
+ :next_cursor,
13
+ keyword_init: true
14
+ )
15
+ def initialize(data:, has_more: false, next_cursor: nil)
16
+ super
17
+ freeze
18
+ end
19
+
20
+ def empty?
21
+ data.empty?
22
+ end
23
+
24
+ def to_h
25
+ {
26
+ data: data,
27
+ has_more: has_more,
28
+ next_cursor: next_cursor
29
+ }
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,48 @@
1
+ module Exa
2
+ module Resources
3
+ # Represents a webset monitor that automates updates on a schedule
4
+ Monitor = Struct.new(
5
+ :id,
6
+ :object,
7
+ :status,
8
+ :webset_id,
9
+ :cadence,
10
+ :behavior,
11
+ :created_at,
12
+ :updated_at,
13
+ keyword_init: true
14
+ ) do
15
+ def freeze
16
+ super
17
+ cadence.freeze if cadence
18
+ behavior.freeze if behavior
19
+ self
20
+ end
21
+
22
+ def pending?
23
+ status == "pending"
24
+ end
25
+
26
+ def active?
27
+ status == "active"
28
+ end
29
+
30
+ def paused?
31
+ status == "paused"
32
+ end
33
+
34
+ def to_h
35
+ {
36
+ id: id,
37
+ object: object,
38
+ status: status,
39
+ webset_id: webset_id,
40
+ cadence: cadence,
41
+ behavior: behavior,
42
+ created_at: created_at,
43
+ updated_at: updated_at
44
+ }.compact
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exa
4
+ module Resources
5
+ # Represents a paginated list of monitors from the Exa API
6
+ class MonitorCollection < Struct.new(
7
+ :data,
8
+ :has_more,
9
+ :next_cursor,
10
+ keyword_init: true
11
+ )
12
+ def initialize(data:, has_more: false, next_cursor: nil)
13
+ super
14
+ freeze
15
+ end
16
+
17
+ def empty?
18
+ data.empty?
19
+ end
20
+
21
+ def to_h
22
+ {
23
+ data: data,
24
+ has_more: has_more,
25
+ next_cursor: next_cursor
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,52 @@
1
+ module Exa
2
+ module Resources
3
+ # Represents a monitor run execution
4
+ MonitorRun = Struct.new(
5
+ :id,
6
+ :object,
7
+ :monitor_id,
8
+ :status,
9
+ :created_at,
10
+ :updated_at,
11
+ :completed_at,
12
+ :failed_at,
13
+ :failed_reason,
14
+ keyword_init: true
15
+ ) do
16
+ def freeze
17
+ super
18
+ self
19
+ end
20
+
21
+ def pending?
22
+ status == "pending"
23
+ end
24
+
25
+ def running?
26
+ status == "running"
27
+ end
28
+
29
+ def completed?
30
+ status == "completed"
31
+ end
32
+
33
+ def failed?
34
+ status == "failed"
35
+ end
36
+
37
+ def to_h
38
+ {
39
+ id: id,
40
+ object: object,
41
+ monitor_id: monitor_id,
42
+ status: status,
43
+ created_at: created_at,
44
+ updated_at: updated_at,
45
+ completed_at: completed_at,
46
+ failed_at: failed_at,
47
+ failed_reason: failed_reason
48
+ }.compact
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exa
4
+ module Resources
5
+ # Represents a paginated list of monitor runs from the Exa API
6
+ class MonitorRunCollection < Struct.new(
7
+ :data,
8
+ :has_more,
9
+ :next_cursor,
10
+ keyword_init: true
11
+ )
12
+ def initialize(data:, has_more: false, next_cursor: nil)
13
+ super
14
+ freeze
15
+ end
16
+
17
+ def empty?
18
+ data.empty?
19
+ end
20
+
21
+ def to_h
22
+ {
23
+ data: data,
24
+ has_more: has_more,
25
+ next_cursor: next_cursor
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../../constants/websets"
4
+
3
5
  module Exa
4
6
  module Services
5
7
  module Websets
6
8
  # Validates parameters for webset creation
7
9
  class CreateValidator
8
- VALID_ENTITY_TYPES = %w[company person article research_paper custom].freeze
9
- VALID_ENRICHMENT_FORMATS = %w[text date number options url].freeze
10
- VALID_SOURCE_TYPES = %w[import webset].freeze
10
+ VALID_ENTITY_TYPES = Constants::Websets::ENTITY_TYPES
11
+ VALID_ENRICHMENT_FORMATS = Constants::Websets::ENRICHMENT_FORMATS
12
+ VALID_SOURCE_TYPES = Constants::Websets::SOURCE_TYPES
11
13
 
12
14
  class << self
13
15
  def validate!(params)