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,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ # typed: strict
4
+
5
+ module Exa
6
+ module Resources
7
+ class SearchResponse < Base
8
+ # @return [String] Unique request identifier
9
+ def request_id
10
+ get(:request_id)
11
+ end
12
+
13
+ # @return [String, nil] The search type that was resolved/used
14
+ def resolved_search_type
15
+ get(:resolved_search_type)
16
+ end
17
+
18
+ # @return [String, nil] The search type (for auto searches)
19
+ def search_type
20
+ get(:search_type)
21
+ end
22
+
23
+ # @return [Array<SearchResult>] Search results
24
+ def results
25
+ @results ||= (get(:results, []) || []).map { |data| SearchResult.new(data) }
26
+ end
27
+
28
+ # @return [String, nil] Combined context string for LLM consumption
29
+ def context
30
+ get(:context)
31
+ end
32
+
33
+ # @return [CostInfo, nil] Cost information for the request
34
+ def cost
35
+ cost_data = get(:cost_dollars)
36
+ return nil unless cost_data
37
+
38
+ CostInfo.new(cost_data)
39
+ end
40
+
41
+ # @return [Float] Total cost in dollars
42
+ def total_cost
43
+ cost&.total || 0.0
44
+ end
45
+
46
+ # @return [Integer] Number of results
47
+ def count
48
+ results.length
49
+ end
50
+
51
+ # @return [Boolean] Whether results are empty
52
+ def empty?
53
+ results.empty?
54
+ end
55
+
56
+ # Iterates over each result
57
+ # @yield [SearchResult] Each result
58
+ # @return [Enumerator, self]
59
+ def each(&block)
60
+ return results.each unless block
61
+
62
+ results.each(&block)
63
+ self
64
+ end
65
+
66
+ # @param index [Integer] Index of result
67
+ # @return [SearchResult, nil] Result at index
68
+ def [](index)
69
+ results[index]
70
+ end
71
+
72
+ # @return [SearchResult, nil] First result
73
+ def first
74
+ results.first
75
+ end
76
+
77
+ # @return [SearchResult, nil] Last result
78
+ def last
79
+ results.last
80
+ end
81
+
82
+ private
83
+
84
+ def inspectable_attributes
85
+ { request_id: request_id, count: count }
86
+ end
87
+ end
88
+
89
+ class CostInfo < Base
90
+ # @return [Float] Total cost in dollars
91
+ def total
92
+ get(:total, 0.0)
93
+ end
94
+
95
+ # @return [Array<Hash>] Breakdown of costs
96
+ def breakdown
97
+ get(:break_down, [])
98
+ end
99
+
100
+ # @return [Hash] Per-request price information
101
+ def per_request_prices
102
+ get(:per_request_prices, {})
103
+ end
104
+
105
+ # @return [Hash] Per-page price information
106
+ def per_page_prices
107
+ get(:per_page_prices, {})
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ # typed: strict
4
+
5
+ module Exa
6
+ module Resources
7
+ class SearchResult < Base
8
+ # @return [String] Unique identifier for the result
9
+ def id
10
+ get(:id)
11
+ end
12
+
13
+ # @return [String] Title of the page
14
+ def title
15
+ get(:title)
16
+ end
17
+
18
+ # @return [String] URL of the page
19
+ def url
20
+ get(:url)
21
+ end
22
+
23
+ # @return [Time, nil] Published date of the content
24
+ def published_date
25
+ date_str = get(:published_date)
26
+ return nil unless date_str
27
+
28
+ Time.parse(date_str)
29
+ rescue ArgumentError
30
+ nil
31
+ end
32
+
33
+ # @return [String, nil] Author of the content
34
+ def author
35
+ get(:author)
36
+ end
37
+
38
+ # @return [String, nil] URL of the page image
39
+ def image
40
+ get(:image)
41
+ end
42
+
43
+ # @return [String, nil] URL of the page favicon
44
+ def favicon
45
+ get(:favicon)
46
+ end
47
+
48
+ # @return [Float, nil] Relevance score
49
+ def score
50
+ get(:score)
51
+ end
52
+
53
+ # @return [String, nil] Full text content of the page
54
+ def text
55
+ get(:text)
56
+ end
57
+
58
+ # @return [Array<String>] Highlighted text snippets
59
+ def highlights
60
+ get(:highlights, [])
61
+ end
62
+
63
+ # @return [Array<Float>] Scores for each highlight
64
+ def highlight_scores
65
+ get(:highlight_scores, [])
66
+ end
67
+
68
+ # @return [String, nil] AI-generated summary
69
+ def summary
70
+ get(:summary)
71
+ end
72
+
73
+ # @return [Array<SearchResult>] Related subpages
74
+ def subpages
75
+ (get(:subpages, []) || []).map { |data| SearchResult.new(data) }
76
+ end
77
+
78
+ # @return [Hash] Extra metadata
79
+ def extras
80
+ get(:extras, {})
81
+ end
82
+
83
+ # @return [Array<String>] Links found on the page
84
+ def links
85
+ dig(:extras, :links) || []
86
+ end
87
+
88
+ private
89
+
90
+ def inspectable_attributes
91
+ { id: id, title: title, url: url }
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ # typed: strict
4
+
5
+ module Exa
6
+ module Resources
7
+ class Webhook < Base
8
+ # @return [String] Unique identifier
9
+ def id
10
+ get(:id)
11
+ end
12
+
13
+ # @return [String] Object type
14
+ def object
15
+ get(:object)
16
+ end
17
+
18
+ # @return [String] Status: active, inactive
19
+ def status
20
+ get(:status)
21
+ end
22
+
23
+ # @return [Array<String>] Subscribed event types
24
+ def events
25
+ get(:events, [])
26
+ end
27
+
28
+ # @return [String] Webhook URL
29
+ def url
30
+ get(:url)
31
+ end
32
+
33
+ # @return [String, nil] Secret for signature verification (only on creation)
34
+ def secret
35
+ get(:secret)
36
+ end
37
+
38
+ # @return [Hash] Custom metadata
39
+ def metadata
40
+ get(:metadata, {})
41
+ end
42
+
43
+ # @return [Time, nil] Creation timestamp
44
+ def created_at
45
+ parse_time(get(:created_at))
46
+ end
47
+
48
+ # @return [Time, nil] Last update timestamp
49
+ def updated_at
50
+ parse_time(get(:updated_at))
51
+ end
52
+
53
+ # @return [Boolean] Whether webhook is active
54
+ def active?
55
+ status == "active"
56
+ end
57
+
58
+ # @return [Boolean] Whether webhook is inactive
59
+ def inactive?
60
+ status == "inactive"
61
+ end
62
+
63
+ private
64
+
65
+ def parse_time(value)
66
+ return nil unless value
67
+
68
+ Time.parse(value)
69
+ rescue ArgumentError
70
+ nil
71
+ end
72
+
73
+ def inspectable_attributes
74
+ { id: id, status: status, url: url }
75
+ end
76
+ end
77
+
78
+ class WebhookAttempt < Base
79
+ # @return [String] Unique identifier
80
+ def id
81
+ get(:id)
82
+ end
83
+
84
+ # @return [String] Object type
85
+ def object
86
+ get(:object)
87
+ end
88
+
89
+ # @return [String] Webhook ID
90
+ def webhook_id
91
+ get(:webhook_id)
92
+ end
93
+
94
+ # @return [String] Event ID
95
+ def event_id
96
+ get(:event_id)
97
+ end
98
+
99
+ # @return [String] Event type
100
+ def event_type
101
+ get(:event_type)
102
+ end
103
+
104
+ # @return [Integer, nil] HTTP response status code
105
+ def response_status
106
+ get(:response_status)
107
+ end
108
+
109
+ # @return [String, nil] Response body
110
+ def response_body
111
+ get(:response_body)
112
+ end
113
+
114
+ # @return [Boolean] Whether delivery succeeded
115
+ def success?
116
+ response_status && response_status >= 200 && response_status < 300
117
+ end
118
+
119
+ # @return [Time, nil] Attempt timestamp
120
+ def attempted_at
121
+ parse_time(get(:attempted_at))
122
+ end
123
+
124
+ # @return [Time, nil] Creation timestamp
125
+ def created_at
126
+ parse_time(get(:created_at))
127
+ end
128
+
129
+ private
130
+
131
+ def parse_time(value)
132
+ return nil unless value
133
+
134
+ Time.parse(value)
135
+ rescue ArgumentError
136
+ nil
137
+ end
138
+ end
139
+
140
+ class WebhookListResponse < PaginatedResponse
141
+ def data
142
+ @data ||= (get(:data, []) || []).map { |item| Webhook.new(item) }
143
+ end
144
+ end
145
+
146
+ class WebhookAttemptListResponse < PaginatedResponse
147
+ def data
148
+ @data ||= (get(:data, []) || []).map { |item| WebhookAttempt.new(item) }
149
+ end
150
+ end
151
+ end
152
+ end