exaonruby 1.0.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 (40) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +614 -0
  4. data/exaonruby.gemspec +37 -0
  5. data/exe/exa +7 -0
  6. data/lib/exa/cli.rb +458 -0
  7. data/lib/exa/client.rb +210 -0
  8. data/lib/exa/configuration.rb +81 -0
  9. data/lib/exa/endpoints/answer.rb +109 -0
  10. data/lib/exa/endpoints/contents.rb +141 -0
  11. data/lib/exa/endpoints/events.rb +71 -0
  12. data/lib/exa/endpoints/find_similar.rb +154 -0
  13. data/lib/exa/endpoints/imports.rb +145 -0
  14. data/lib/exa/endpoints/monitors.rb +193 -0
  15. data/lib/exa/endpoints/research.rb +158 -0
  16. data/lib/exa/endpoints/search.rb +195 -0
  17. data/lib/exa/endpoints/webhooks.rb +161 -0
  18. data/lib/exa/endpoints/webset_enrichments.rb +162 -0
  19. data/lib/exa/endpoints/webset_items.rb +90 -0
  20. data/lib/exa/endpoints/webset_searches.rb +137 -0
  21. data/lib/exa/endpoints/websets.rb +214 -0
  22. data/lib/exa/errors.rb +180 -0
  23. data/lib/exa/resources/answer_response.rb +101 -0
  24. data/lib/exa/resources/base.rb +56 -0
  25. data/lib/exa/resources/contents_response.rb +123 -0
  26. data/lib/exa/resources/event.rb +84 -0
  27. data/lib/exa/resources/import.rb +137 -0
  28. data/lib/exa/resources/monitor.rb +205 -0
  29. data/lib/exa/resources/paginated_response.rb +87 -0
  30. data/lib/exa/resources/research_task.rb +165 -0
  31. data/lib/exa/resources/search_response.rb +111 -0
  32. data/lib/exa/resources/search_result.rb +95 -0
  33. data/lib/exa/resources/webhook.rb +152 -0
  34. data/lib/exa/resources/webset.rb +491 -0
  35. data/lib/exa/resources/webset_item.rb +256 -0
  36. data/lib/exa/utils/parameter_converter.rb +159 -0
  37. data/lib/exa/utils/webhook_handler.rb +239 -0
  38. data/lib/exa/version.rb +7 -0
  39. data/lib/exa.rb +130 -0
  40. metadata +146 -0
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ # typed: strict
4
+
5
+ module Exa
6
+ module Endpoints
7
+ module Webhooks
8
+ VALID_EVENTS = %w[
9
+ webset.created webset.deleted webset.paused webset.idle
10
+ webset.search.created webset.search.canceled webset.search.completed webset.search.updated
11
+ import.created import.completed
12
+ webset.item.created webset.item.enriched
13
+ monitor.created monitor.updated monitor.deleted
14
+ monitor.run.created monitor.run.completed
15
+ webset.export.created webset.export.completed
16
+ ].freeze
17
+
18
+ # Creates a new Webhook for event notifications
19
+ #
20
+ # Webhooks notify you when events happen in your Websets via HTTP POST.
21
+ # The response includes a secret key for signature verification.
22
+ #
23
+ # @param url [String] URL to send webhook notifications to
24
+ # @param events [Array<String>] Event types to subscribe to
25
+ # @param metadata [Hash, nil] Custom metadata
26
+ #
27
+ # @return [Exa::Resources::Webhook] Created Webhook with secret
28
+ #
29
+ # @example Create a webhook for item events
30
+ # webhook = client.create_webhook(
31
+ # url: "https://example.com/webhooks/exa",
32
+ # events: ["webset.item.created", "webset.item.enriched"]
33
+ # )
34
+ # puts "Secret (save this!): #{webhook.secret}"
35
+ def create_webhook(url:, events:, metadata: nil)
36
+ validate_webhook_params!(url, events)
37
+
38
+ params = {
39
+ url: url,
40
+ events: events
41
+ }
42
+ params[:metadata] = metadata if metadata
43
+
44
+ response = websets_post("/webhooks", params)
45
+
46
+ Resources::Webhook.new(
47
+ Utils::ParameterConverter.from_api_response(response)
48
+ )
49
+ end
50
+
51
+ # Gets a Webhook by ID
52
+ #
53
+ # @param webhook_id [String] Webhook ID
54
+ # @return [Exa::Resources::Webhook] The Webhook
55
+ def get_webhook(webhook_id)
56
+ raise InvalidRequestError, "webhook_id must be a non-empty string" if !webhook_id.is_a?(String) || webhook_id.empty?
57
+
58
+ response = websets_get("/webhooks/#{webhook_id}")
59
+
60
+ Resources::Webhook.new(
61
+ Utils::ParameterConverter.from_api_response(response)
62
+ )
63
+ end
64
+
65
+ # Lists all Webhooks
66
+ #
67
+ # @param cursor [String, nil] Cursor for pagination
68
+ # @param limit [Integer, nil] Number of results per page
69
+ #
70
+ # @return [Exa::Resources::WebhookListResponse] Paginated list of Webhooks
71
+ def list_webhooks(cursor: nil, limit: nil)
72
+ params = {}
73
+ params[:cursor] = cursor if cursor
74
+ params[:limit] = limit if limit
75
+
76
+ response = websets_get("/webhooks", params)
77
+
78
+ Resources::WebhookListResponse.new(
79
+ Utils::ParameterConverter.from_api_response(response)
80
+ )
81
+ end
82
+
83
+ # Updates a Webhook
84
+ #
85
+ # @param webhook_id [String] Webhook ID
86
+ # @param url [String, nil] Updated URL
87
+ # @param events [Array<String>, nil] Updated event subscriptions
88
+ # @param status [String, nil] "active" or "inactive"
89
+ # @param metadata [Hash, nil] Updated metadata
90
+ #
91
+ # @return [Exa::Resources::Webhook] Updated Webhook
92
+ def update_webhook(webhook_id, url: nil, events: nil, status: nil, metadata: nil)
93
+ raise InvalidRequestError, "webhook_id must be a non-empty string" if !webhook_id.is_a?(String) || webhook_id.empty?
94
+
95
+ if events
96
+ validate_events!(events)
97
+ end
98
+
99
+ params = {}
100
+ params[:url] = url if url
101
+ params[:events] = events if events
102
+ params[:status] = status if status
103
+ params[:metadata] = metadata if metadata
104
+
105
+ response = websets_patch("/webhooks/#{webhook_id}", params)
106
+
107
+ Resources::Webhook.new(
108
+ Utils::ParameterConverter.from_api_response(response)
109
+ )
110
+ end
111
+
112
+ # Deletes a Webhook
113
+ #
114
+ # @param webhook_id [String] Webhook ID
115
+ # @return [Hash] Deletion confirmation
116
+ def delete_webhook(webhook_id)
117
+ raise InvalidRequestError, "webhook_id must be a non-empty string" if !webhook_id.is_a?(String) || webhook_id.empty?
118
+
119
+ websets_delete("/webhooks/#{webhook_id}")
120
+ end
121
+
122
+ # Lists delivery attempts for a Webhook
123
+ #
124
+ # @param webhook_id [String] Webhook ID
125
+ # @param cursor [String, nil] Cursor for pagination
126
+ # @param limit [Integer, nil] Number of results per page
127
+ #
128
+ # @return [Exa::Resources::WebhookAttemptListResponse] Paginated list of attempts
129
+ def list_webhook_attempts(webhook_id, cursor: nil, limit: nil)
130
+ raise InvalidRequestError, "webhook_id must be a non-empty string" if !webhook_id.is_a?(String) || webhook_id.empty?
131
+
132
+ params = {}
133
+ params[:cursor] = cursor if cursor
134
+ params[:limit] = limit if limit
135
+
136
+ response = websets_get("/webhooks/#{webhook_id}/attempts", params)
137
+
138
+ Resources::WebhookAttemptListResponse.new(
139
+ Utils::ParameterConverter.from_api_response(response)
140
+ )
141
+ end
142
+
143
+ private
144
+
145
+ def validate_webhook_params!(url, events)
146
+ raise InvalidRequestError, "url must be a non-empty string" if !url.is_a?(String) || url.empty?
147
+ raise InvalidRequestError, "events must be a non-empty array" if !events.is_a?(Array) || events.empty?
148
+
149
+ validate_events!(events)
150
+ end
151
+
152
+ def validate_events!(events)
153
+ events.each do |event|
154
+ unless VALID_EVENTS.include?(event)
155
+ raise InvalidRequestError, "Invalid event: #{event}. Valid events: #{VALID_EVENTS.join(", ")}"
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ # typed: strict
4
+
5
+ module Exa
6
+ module Endpoints
7
+ module WebsetEnrichments
8
+ VALID_FORMATS = %w[text enum number boolean date].freeze
9
+
10
+ # Creates a new Enrichment for a Webset
11
+ #
12
+ # Enrichments automatically search for and extract specific information
13
+ # from each Item added to the Webset.
14
+ #
15
+ # @param webset_id [String] Webset ID or external ID
16
+ # @param description [String] Description of what to extract
17
+ # @param format [String] Output format: text, enum, number, boolean, date
18
+ # @param options [Array<Hash>] Options for enum format [{ label: "..." }]
19
+ # @param instructions [String] Additional instructions for extraction
20
+ # @param metadata [Hash] Custom metadata
21
+ #
22
+ # @return [Exa::Resources::WebsetEnrichment] Created Enrichment
23
+ #
24
+ # @raise [Exa::NotFoundError] if Webset not found
25
+ #
26
+ # @example Create a text enrichment
27
+ # enrichment = client.create_webset_enrichment(
28
+ # "webset_abc123",
29
+ # description: "Company's primary product or service",
30
+ # format: "text"
31
+ # )
32
+ #
33
+ # @example Create an enum enrichment
34
+ # enrichment = client.create_webset_enrichment(
35
+ # "webset_abc123",
36
+ # description: "Company's funding stage",
37
+ # format: "enum",
38
+ # options: [
39
+ # { label: "Pre-seed" },
40
+ # { label: "Seed" },
41
+ # { label: "Series A" },
42
+ # { label: "Series B+" }
43
+ # ]
44
+ # )
45
+ #
46
+ # @example Create a number enrichment
47
+ # enrichment = client.create_webset_enrichment(
48
+ # "webset_abc123",
49
+ # description: "Number of employees",
50
+ # format: "number"
51
+ # )
52
+ def create_webset_enrichment(webset_id, **enrichment_options)
53
+ raise InvalidRequestError, "webset_id must be a non-empty string" if !webset_id.is_a?(String) || webset_id.empty?
54
+ raise InvalidRequestError, "description is required" unless enrichment_options[:description]
55
+
56
+ validate_enrichment_options!(enrichment_options)
57
+
58
+ params = build_enrichment_params(enrichment_options)
59
+ response = websets_post("/websets/#{webset_id}/enrichments", params)
60
+
61
+ Resources::WebsetEnrichment.new(
62
+ Utils::ParameterConverter.from_api_response(response)
63
+ )
64
+ end
65
+
66
+ # Lists all Enrichments for a Webset
67
+ #
68
+ # @param webset_id [String] Webset ID or external ID
69
+ #
70
+ # @return [Array<Exa::Resources::WebsetEnrichment>] List of Enrichments
71
+ #
72
+ # @raise [Exa::NotFoundError] if Webset not found
73
+ #
74
+ # @example List Enrichments
75
+ # enrichments = client.list_webset_enrichments("webset_abc123")
76
+ # enrichments.each { |e| puts e.description }
77
+ def list_webset_enrichments(webset_id)
78
+ raise InvalidRequestError, "webset_id must be a non-empty string" if !webset_id.is_a?(String) || webset_id.empty?
79
+
80
+ response = websets_get("/websets/#{webset_id}/enrichments")
81
+
82
+ enrichments_data = response.is_a?(Hash) && response[:data] ? response[:data] : response
83
+ enrichments_data = [enrichments_data] unless enrichments_data.is_a?(Array)
84
+
85
+ enrichments_data.map do |data|
86
+ Resources::WebsetEnrichment.new(
87
+ Utils::ParameterConverter.from_api_response(data)
88
+ )
89
+ end
90
+ end
91
+
92
+ # Gets an Enrichment by ID
93
+ #
94
+ # @param webset_id [String] Webset ID or external ID
95
+ # @param enrichment_id [String] Enrichment ID
96
+ #
97
+ # @return [Exa::Resources::WebsetEnrichment] The Enrichment
98
+ #
99
+ # @raise [Exa::NotFoundError] if Webset or Enrichment not found
100
+ #
101
+ # @example Get an Enrichment
102
+ # enrichment = client.get_webset_enrichment("webset_abc123", "enrichment_xyz789")
103
+ def get_webset_enrichment(webset_id, enrichment_id)
104
+ raise InvalidRequestError, "webset_id must be a non-empty string" if !webset_id.is_a?(String) || webset_id.empty?
105
+ raise InvalidRequestError, "enrichment_id must be a non-empty string" if !enrichment_id.is_a?(String) || enrichment_id.empty?
106
+
107
+ response = websets_get("/websets/#{webset_id}/enrichments/#{enrichment_id}")
108
+
109
+ Resources::WebsetEnrichment.new(
110
+ Utils::ParameterConverter.from_api_response(response)
111
+ )
112
+ end
113
+
114
+ # Deletes an Enrichment from a Webset
115
+ #
116
+ # @param webset_id [String] Webset ID or external ID
117
+ # @param enrichment_id [String] Enrichment ID
118
+ #
119
+ # @return [Hash] Deletion confirmation
120
+ #
121
+ # @raise [Exa::NotFoundError] if Webset or Enrichment not found
122
+ #
123
+ # @example Delete an Enrichment
124
+ # client.delete_webset_enrichment("webset_abc123", "enrichment_xyz789")
125
+ def delete_webset_enrichment(webset_id, enrichment_id)
126
+ raise InvalidRequestError, "webset_id must be a non-empty string" if !webset_id.is_a?(String) || webset_id.empty?
127
+ raise InvalidRequestError, "enrichment_id must be a non-empty string" if !enrichment_id.is_a?(String) || enrichment_id.empty?
128
+
129
+ websets_delete("/websets/#{webset_id}/enrichments/#{enrichment_id}")
130
+ end
131
+
132
+ private
133
+
134
+ # @param options [Hash] Options to validate
135
+ def validate_enrichment_options!(options)
136
+ if options[:format]
137
+ format = options[:format].to_s
138
+ unless VALID_FORMATS.include?(format)
139
+ raise InvalidRequestError, "Invalid format: #{format}. Valid formats: #{VALID_FORMATS.join(", ")}"
140
+ end
141
+
142
+ if format == "enum" && (!options[:options] || options[:options].empty?)
143
+ raise InvalidRequestError, "options are required when format is 'enum'"
144
+ end
145
+ end
146
+ end
147
+
148
+ # @param options [Hash] Enrichment options
149
+ # @return [Hash] API-formatted parameters
150
+ def build_enrichment_params(options)
151
+ params = { description: options[:description] }
152
+
153
+ params[:format] = options[:format] if options[:format]
154
+ params[:options] = options[:options] if options[:options]
155
+ params[:instructions] = options[:instructions] if options[:instructions]
156
+ params[:metadata] = options[:metadata] if options[:metadata]
157
+
158
+ params
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ # typed: strict
4
+
5
+ module Exa
6
+ module Endpoints
7
+ module WebsetItems
8
+ # Lists all Items in a Webset with pagination
9
+ #
10
+ # @param webset_id [String] Webset ID or external ID
11
+ # @param cursor [String, nil] Cursor for pagination
12
+ # @param limit [Integer, nil] Number of results per page (1-100)
13
+ # @param source_id [String, nil] Filter by source ID
14
+ #
15
+ # @return [Exa::Resources::WebsetItemsListResponse] Paginated list of Items
16
+ #
17
+ # @raise [Exa::NotFoundError] if Webset not found
18
+ #
19
+ # @example List all Items in a Webset
20
+ # response = client.list_webset_items("webset_abc123")
21
+ # response.data.each { |item| puts item.url }
22
+ #
23
+ # @example Paginate through Items
24
+ # response = client.list_webset_items("webset_abc123", limit: 50)
25
+ # all_items = response.data.dup
26
+ # while response.has_more?
27
+ # response = client.list_webset_items("webset_abc123", cursor: response.next_cursor)
28
+ # all_items.concat(response.data)
29
+ # end
30
+ def list_webset_items(webset_id, cursor: nil, limit: nil, source_id: nil)
31
+ raise InvalidRequestError, "webset_id must be a non-empty string" if !webset_id.is_a?(String) || webset_id.empty?
32
+
33
+ if limit && (limit < 1 || limit > 100)
34
+ raise InvalidRequestError, "limit must be between 1 and 100"
35
+ end
36
+
37
+ params = {}
38
+ params[:cursor] = cursor if cursor
39
+ params[:limit] = limit if limit
40
+ params[:sourceId] = source_id if source_id
41
+
42
+ response = websets_get("/websets/#{webset_id}/items", params)
43
+
44
+ Resources::WebsetItemsListResponse.new(
45
+ Utils::ParameterConverter.from_api_response(response)
46
+ )
47
+ end
48
+
49
+ # Gets a specific Item from a Webset
50
+ #
51
+ # @param webset_id [String] Webset ID or external ID
52
+ # @param item_id [String] Item ID
53
+ #
54
+ # @return [Exa::Resources::WebsetItem] The Item
55
+ #
56
+ # @raise [Exa::NotFoundError] if Webset or Item not found
57
+ #
58
+ # @example Get an Item
59
+ # item = client.get_webset_item("webset_abc123", "item_xyz789")
60
+ def get_webset_item(webset_id, item_id)
61
+ raise InvalidRequestError, "webset_id must be a non-empty string" if !webset_id.is_a?(String) || webset_id.empty?
62
+ raise InvalidRequestError, "item_id must be a non-empty string" if !item_id.is_a?(String) || item_id.empty?
63
+
64
+ response = websets_get("/websets/#{webset_id}/items/#{item_id}")
65
+
66
+ Resources::WebsetItem.new(
67
+ Utils::ParameterConverter.from_api_response(response)
68
+ )
69
+ end
70
+
71
+ # Deletes an Item from a Webset
72
+ #
73
+ # @param webset_id [String] Webset ID or external ID
74
+ # @param item_id [String] Item ID
75
+ #
76
+ # @return [Hash] Deletion confirmation
77
+ #
78
+ # @raise [Exa::NotFoundError] if Webset or Item not found
79
+ #
80
+ # @example Delete an Item
81
+ # client.delete_webset_item("webset_abc123", "item_xyz789")
82
+ def delete_webset_item(webset_id, item_id)
83
+ raise InvalidRequestError, "webset_id must be a non-empty string" if !webset_id.is_a?(String) || webset_id.empty?
84
+ raise InvalidRequestError, "item_id must be a non-empty string" if !item_id.is_a?(String) || item_id.empty?
85
+
86
+ websets_delete("/websets/#{webset_id}/items/#{item_id}")
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ # typed: strict
4
+
5
+ module Exa
6
+ module Endpoints
7
+ module WebsetSearches
8
+ VALID_ENTITY_TYPES = %w[company person research_paper].freeze
9
+ VALID_BEHAVIORS = %w[override append].freeze
10
+
11
+ # Creates a new Search for a Webset
12
+ #
13
+ # @param webset_id [String] Webset ID or external ID
14
+ # @param query [String] Search query
15
+ # @param count [Integer] Target number of results
16
+ # @param entity [Hash] Entity type configuration { type: "company"|"person"|"research_paper" }
17
+ # @param criteria [Array<Hash>] Criteria for filtering [{ description: "..." }]
18
+ # @param recall [Boolean] Enable recall estimation
19
+ # @param exclude [Array<Hash>] Exclusion rules
20
+ # @param scope [Array<Hash>] Scope configuration
21
+ # @param behavior [String] Behavior: "override" or "append"
22
+ # @param metadata [Hash] Custom metadata
23
+ #
24
+ # @return [Exa::Resources::WebsetSearch] Created Search
25
+ #
26
+ # @raise [Exa::NotFoundError] if Webset not found
27
+ #
28
+ # @example Create a Search
29
+ # search = client.create_webset_search(
30
+ # "webset_abc123",
31
+ # query: "AI startups in healthcare",
32
+ # count: 100,
33
+ # entity: { type: "company" },
34
+ # criteria: [{ description: "Must be in healthcare industry" }]
35
+ # )
36
+ def create_webset_search(webset_id, **options)
37
+ raise InvalidRequestError, "webset_id must be a non-empty string" if !webset_id.is_a?(String) || webset_id.empty?
38
+ raise InvalidRequestError, "query is required" unless options[:query]
39
+
40
+ validate_webset_search_options!(options)
41
+
42
+ params = build_webset_search_params(options)
43
+ response = websets_post("/websets/#{webset_id}/searches", params)
44
+
45
+ Resources::WebsetSearch.new(
46
+ Utils::ParameterConverter.from_api_response(response)
47
+ )
48
+ end
49
+
50
+ # Gets a Search by ID
51
+ #
52
+ # @param webset_id [String] Webset ID or external ID
53
+ # @param search_id [String] Search ID
54
+ #
55
+ # @return [Exa::Resources::WebsetSearch] The Search
56
+ #
57
+ # @raise [Exa::NotFoundError] if Webset or Search not found
58
+ #
59
+ # @example Get a Search with progress
60
+ # search = client.get_webset_search("webset_abc123", "search_xyz789")
61
+ # puts "Progress: #{search.completion_percentage}%"
62
+ def get_webset_search(webset_id, search_id)
63
+ raise InvalidRequestError, "webset_id must be a non-empty string" if !webset_id.is_a?(String) || webset_id.empty?
64
+ raise InvalidRequestError, "search_id must be a non-empty string" if !search_id.is_a?(String) || search_id.empty?
65
+
66
+ response = websets_get("/websets/#{webset_id}/searches/#{search_id}")
67
+
68
+ Resources::WebsetSearch.new(
69
+ Utils::ParameterConverter.from_api_response(response)
70
+ )
71
+ end
72
+
73
+ # Cancels an in-progress Search
74
+ #
75
+ # @param webset_id [String] Webset ID or external ID
76
+ # @param search_id [String] Search ID
77
+ #
78
+ # @return [Exa::Resources::WebsetSearch] The canceled Search
79
+ #
80
+ # @raise [Exa::NotFoundError] if Webset or Search not found
81
+ #
82
+ # @example Cancel a Search
83
+ # search = client.cancel_webset_search("webset_abc123", "search_xyz789")
84
+ # puts "Canceled at: #{search.canceled_at}"
85
+ def cancel_webset_search(webset_id, search_id)
86
+ raise InvalidRequestError, "webset_id must be a non-empty string" if !webset_id.is_a?(String) || webset_id.empty?
87
+ raise InvalidRequestError, "search_id must be a non-empty string" if !search_id.is_a?(String) || search_id.empty?
88
+
89
+ response = websets_post("/websets/#{webset_id}/searches/#{search_id}/cancel", {})
90
+
91
+ Resources::WebsetSearch.new(
92
+ Utils::ParameterConverter.from_api_response(response)
93
+ )
94
+ end
95
+
96
+ private
97
+
98
+ # @param options [Hash] Options to validate
99
+ def validate_webset_search_options!(options)
100
+ if options[:entity] && options[:entity][:type]
101
+ entity_type = options[:entity][:type].to_s
102
+ unless VALID_ENTITY_TYPES.include?(entity_type)
103
+ raise InvalidRequestError, "Invalid entity type: #{entity_type}. Valid types: #{VALID_ENTITY_TYPES.join(", ")}"
104
+ end
105
+ end
106
+
107
+ if options[:behavior]
108
+ behavior = options[:behavior].to_s
109
+ unless VALID_BEHAVIORS.include?(behavior)
110
+ raise InvalidRequestError, "Invalid behavior: #{behavior}. Valid behaviors: #{VALID_BEHAVIORS.join(", ")}"
111
+ end
112
+ end
113
+
114
+ if options[:count] && (options[:count] < 1 || options[:count] > 10_000)
115
+ raise InvalidRequestError, "count must be between 1 and 10000"
116
+ end
117
+ end
118
+
119
+ # @param options [Hash] Search options
120
+ # @return [Hash] API-formatted parameters
121
+ def build_webset_search_params(options)
122
+ params = { query: options[:query] }
123
+
124
+ params[:count] = options[:count] if options[:count]
125
+ params[:entity] = options[:entity] if options[:entity]
126
+ params[:criteria] = options[:criteria] if options[:criteria]
127
+ params[:recall] = options[:recall] if options.key?(:recall)
128
+ params[:exclude] = options[:exclude] if options[:exclude]
129
+ params[:scope] = options[:scope] if options[:scope]
130
+ params[:behavior] = options[:behavior] if options[:behavior]
131
+ params[:metadata] = options[:metadata] if options[:metadata]
132
+
133
+ params
134
+ end
135
+ end
136
+ end
137
+ end