tavily 0.1.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 +7 -0
- data/CHANGELOG.md +30 -0
- data/LICENSE.txt +21 -0
- data/README.md +319 -0
- data/lib/tavily/client.rb +276 -0
- data/lib/tavily/configuration.rb +69 -0
- data/lib/tavily/connection.rb +298 -0
- data/lib/tavily/errors.rb +95 -0
- data/lib/tavily/object.rb +80 -0
- data/lib/tavily/responses.rb +197 -0
- data/lib/tavily/version.rb +5 -0
- data/lib/tavily.rb +78 -0
- data/sig/tavily/client.rbs +107 -0
- data/sig/tavily/configuration.rbs +23 -0
- data/sig/tavily/connection.rbs +12 -0
- data/sig/tavily/errors.rbs +57 -0
- data/sig/tavily/object.rbs +18 -0
- data/sig/tavily/responses.rbs +108 -0
- data/sig/tavily.rbs +19 -0
- metadata +65 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "object"
|
|
4
|
+
|
|
5
|
+
module Tavily
|
|
6
|
+
# Credit usage information, present when +include_usage: true+ is requested.
|
|
7
|
+
class Usage < Object
|
|
8
|
+
# @return [Integer, nil] number of API credits consumed by the request.
|
|
9
|
+
attribute :credits
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# An image associated with a search result. Tavily returns images either as
|
|
13
|
+
# bare URL strings or as objects with a description; this normalizes both.
|
|
14
|
+
class Image < Object
|
|
15
|
+
# @return [String, nil] image URL.
|
|
16
|
+
attribute :url
|
|
17
|
+
# @return [String, nil] generated description (when image descriptions requested).
|
|
18
|
+
attribute :description
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# A single web result from {Client#search}.
|
|
22
|
+
class SearchResult < Object
|
|
23
|
+
# @return [String, nil] page title.
|
|
24
|
+
attribute :title
|
|
25
|
+
# @return [String, nil] result URL.
|
|
26
|
+
attribute :url
|
|
27
|
+
# @return [String, nil] short relevant snippet.
|
|
28
|
+
attribute :content
|
|
29
|
+
# @return [Float, nil] relevance score (0.0–1.0).
|
|
30
|
+
attribute :score
|
|
31
|
+
# @return [String, nil] full cleaned page content (when raw content requested).
|
|
32
|
+
attribute :raw_content
|
|
33
|
+
# @return [String, nil] favicon URL (when +include_favicon: true+).
|
|
34
|
+
attribute :favicon
|
|
35
|
+
# @return [String, nil] publication date (present for +topic: "news"+).
|
|
36
|
+
attribute :published_date
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Mixin adding +usage+/+credits+/+request_id+/+response_time+ accessors shared
|
|
40
|
+
# by every top-level response.
|
|
41
|
+
module Envelope
|
|
42
|
+
def self.included(base)
|
|
43
|
+
base.attribute :response_time
|
|
44
|
+
base.attribute :request_id
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @return [Usage, nil] credit usage details (when +include_usage: true+).
|
|
48
|
+
def usage
|
|
49
|
+
raw = self["usage"]
|
|
50
|
+
raw.is_a?(Hash) ? Usage.new(raw) : nil
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# @return [Integer, nil] convenience accessor for +usage.credits+.
|
|
54
|
+
def credits
|
|
55
|
+
usage&.credits
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Response from {Client#search}.
|
|
60
|
+
class SearchResponse < Object
|
|
61
|
+
include Envelope
|
|
62
|
+
|
|
63
|
+
# @return [String] the executed query.
|
|
64
|
+
attribute :query
|
|
65
|
+
# @return [String, nil] LLM-generated answer (when +include_answer+ requested).
|
|
66
|
+
attribute :answer
|
|
67
|
+
# @return [Array, nil] suggested follow-up questions, if any.
|
|
68
|
+
attribute :follow_up_questions
|
|
69
|
+
# @return [Hash, nil] parameters auto-selected by Tavily (when +auto_parameters: true+).
|
|
70
|
+
attribute :auto_parameters
|
|
71
|
+
# @return [Array<SearchResult>] ranked results.
|
|
72
|
+
attribute :results, wrap: SearchResult, collection: true
|
|
73
|
+
|
|
74
|
+
# @return [Array<Image>] related images (normalizes string and object forms).
|
|
75
|
+
def images
|
|
76
|
+
Array(self["images"]).map do |img|
|
|
77
|
+
img.is_a?(Hash) ? Image.new(img) : Image.new("url" => img)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# @return [Array<String>] convenience list of result URLs.
|
|
82
|
+
def urls
|
|
83
|
+
results.map(&:url)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# A single successfully extracted page from {Client#extract}.
|
|
88
|
+
class ExtractResult < Object
|
|
89
|
+
# @return [String, nil] the extracted URL.
|
|
90
|
+
attribute :url
|
|
91
|
+
# @return [String, nil] extracted content (markdown or text).
|
|
92
|
+
attribute :raw_content
|
|
93
|
+
# @return [Array<String>] image URLs (when +include_images: true+).
|
|
94
|
+
attribute :images
|
|
95
|
+
# @return [String, nil] favicon URL (when +include_favicon: true+).
|
|
96
|
+
attribute :favicon
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# A URL that failed extraction.
|
|
100
|
+
class FailedResult < Object
|
|
101
|
+
# @return [String, nil] the URL that failed.
|
|
102
|
+
attribute :url
|
|
103
|
+
# @return [String, nil] reason for the failure.
|
|
104
|
+
attribute :error
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Response from {Client#extract}.
|
|
108
|
+
class ExtractResponse < Object
|
|
109
|
+
include Envelope
|
|
110
|
+
|
|
111
|
+
# @return [Array<ExtractResult>] successfully extracted pages.
|
|
112
|
+
attribute :results, wrap: ExtractResult, collection: true
|
|
113
|
+
# @return [Array<FailedResult>] URLs that could not be extracted.
|
|
114
|
+
attribute :failed_results, wrap: FailedResult, collection: true
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# A single page discovered by {Client#crawl}.
|
|
118
|
+
class CrawlResult < Object
|
|
119
|
+
# @return [String, nil] page URL.
|
|
120
|
+
attribute :url
|
|
121
|
+
# @return [String, nil] extracted content (markdown or text).
|
|
122
|
+
attribute :raw_content
|
|
123
|
+
# @return [String, nil] favicon URL (when +include_favicon: true+).
|
|
124
|
+
attribute :favicon
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Response from {Client#crawl}.
|
|
128
|
+
class CrawlResponse < Object
|
|
129
|
+
include Envelope
|
|
130
|
+
|
|
131
|
+
# @return [String, nil] the root URL that was crawled.
|
|
132
|
+
attribute :base_url
|
|
133
|
+
# @return [Array<CrawlResult>] crawled pages.
|
|
134
|
+
attribute :results, wrap: CrawlResult, collection: true
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Response from {Client#map}.
|
|
138
|
+
class MapResponse < Object
|
|
139
|
+
include Envelope
|
|
140
|
+
|
|
141
|
+
# @return [String, nil] the root URL that was mapped.
|
|
142
|
+
attribute :base_url
|
|
143
|
+
# @return [Array<String>] discovered URLs.
|
|
144
|
+
attribute :results
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# A source cited by a research task.
|
|
148
|
+
class ResearchSource < Object
|
|
149
|
+
# @return [String, nil] source title.
|
|
150
|
+
attribute :title
|
|
151
|
+
# @return [String, nil] source URL.
|
|
152
|
+
attribute :url
|
|
153
|
+
# @return [String, nil] favicon URL.
|
|
154
|
+
attribute :favicon
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# A research task, returned by {Client#research} (status +pending+) and by
|
|
158
|
+
# {Client#research_task} / {Client#wait_for_research} (with the final result).
|
|
159
|
+
class ResearchTask < Object
|
|
160
|
+
include Envelope
|
|
161
|
+
|
|
162
|
+
# @return [String, nil] research task id (use to poll for results).
|
|
163
|
+
attribute :request_id
|
|
164
|
+
# @return [String, nil] creation timestamp (ISO 8601).
|
|
165
|
+
attribute :created_at
|
|
166
|
+
# @return [String, nil] one of "pending", "in_progress", "completed", "failed".
|
|
167
|
+
attribute :status
|
|
168
|
+
# @return [String, nil] echo of the research input.
|
|
169
|
+
attribute :input
|
|
170
|
+
# @return [String, nil] the model used ("mini", "pro", or resolved from "auto").
|
|
171
|
+
attribute :model
|
|
172
|
+
# @return [String, Hash, nil] the final report (String, or Hash when +output_schema+ used).
|
|
173
|
+
attribute :content
|
|
174
|
+
# @return [Array<ResearchSource>] sources used in the research.
|
|
175
|
+
attribute :sources, wrap: ResearchSource, collection: true
|
|
176
|
+
|
|
177
|
+
# @return [Boolean] whether the task finished successfully.
|
|
178
|
+
def completed?
|
|
179
|
+
status == "completed"
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# @return [Boolean] whether the task failed.
|
|
183
|
+
def failed?
|
|
184
|
+
status == "failed"
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# @return [Boolean] whether the task is still running or queued.
|
|
188
|
+
def pending?
|
|
189
|
+
%w[pending in_progress].include?(status)
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# A single Server-Sent Event emitted by streaming research
|
|
194
|
+
# ({Client#research} with a block). +data+ is the parsed JSON payload when
|
|
195
|
+
# possible, otherwise the raw string.
|
|
196
|
+
ResearchEvent = Struct.new(:event, :data, keyword_init: true)
|
|
197
|
+
end
|
data/lib/tavily.rb
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "tavily/version"
|
|
4
|
+
require_relative "tavily/errors"
|
|
5
|
+
require_relative "tavily/configuration"
|
|
6
|
+
require_relative "tavily/object"
|
|
7
|
+
require_relative "tavily/responses"
|
|
8
|
+
require_relative "tavily/connection"
|
|
9
|
+
require_relative "tavily/client"
|
|
10
|
+
|
|
11
|
+
# Ruby client for the {https://docs.tavily.com Tavily} web search, extract,
|
|
12
|
+
# crawl, map, and research API.
|
|
13
|
+
#
|
|
14
|
+
# @example One-off call using the global configuration
|
|
15
|
+
# Tavily.configure { |c| c.api_key = ENV["TAVILY_API_KEY"] }
|
|
16
|
+
# Tavily.search("latest ruby release").results.first.url
|
|
17
|
+
#
|
|
18
|
+
# @example Dedicated client
|
|
19
|
+
# client = Tavily::Client.new(api_key: "tvly-...")
|
|
20
|
+
# client.extract("https://example.com")
|
|
21
|
+
module Tavily
|
|
22
|
+
class << self
|
|
23
|
+
# The global configuration shared by {Tavily.search} and friends, and used
|
|
24
|
+
# as the default for new {Client} instances.
|
|
25
|
+
# @return [Configuration]
|
|
26
|
+
def configuration
|
|
27
|
+
@configuration ||= Configuration.new
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Configure the library.
|
|
31
|
+
# @yieldparam config [Configuration]
|
|
32
|
+
# @return [Configuration]
|
|
33
|
+
def configure
|
|
34
|
+
yield(configuration) if block_given?
|
|
35
|
+
reset_default_client!
|
|
36
|
+
configuration
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Reset the global configuration to defaults (re-reads ENV). Mainly useful
|
|
40
|
+
# in tests.
|
|
41
|
+
# @return [Configuration]
|
|
42
|
+
def reset_configuration!
|
|
43
|
+
@configuration = Configuration.new
|
|
44
|
+
reset_default_client!
|
|
45
|
+
@configuration
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# A process-wide {Client} built from the global {.configuration}.
|
|
49
|
+
# @return [Client]
|
|
50
|
+
def default_client
|
|
51
|
+
@default_client ||= Client.new
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @api private
|
|
55
|
+
def reset_default_client!
|
|
56
|
+
@default_client = nil
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @see Client#search
|
|
60
|
+
def search(...) = default_client.search(...)
|
|
61
|
+
# @see Client#qna_search
|
|
62
|
+
def qna_search(...) = default_client.qna_search(...)
|
|
63
|
+
# @see Client#search_context
|
|
64
|
+
def search_context(...) = default_client.search_context(...)
|
|
65
|
+
# @see Client#extract
|
|
66
|
+
def extract(...) = default_client.extract(...)
|
|
67
|
+
# @see Client#crawl
|
|
68
|
+
def crawl(...) = default_client.crawl(...)
|
|
69
|
+
# @see Client#map
|
|
70
|
+
def map(...) = default_client.map(...)
|
|
71
|
+
# @see Client#research
|
|
72
|
+
def research(...) = default_client.research(...)
|
|
73
|
+
# @see Client#research_task
|
|
74
|
+
def research_task(...) = default_client.research_task(...)
|
|
75
|
+
# @see Client#wait_for_research
|
|
76
|
+
def wait_for_research(...) = default_client.wait_for_research(...)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
module Tavily
|
|
2
|
+
class Client
|
|
3
|
+
DEFAULT_POLL_INTERVAL: Float
|
|
4
|
+
DEFAULT_POLL_TIMEOUT: Integer
|
|
5
|
+
|
|
6
|
+
attr_reader config: Configuration
|
|
7
|
+
|
|
8
|
+
def initialize: (?api_key: String?, **untyped) -> void
|
|
9
|
+
|
|
10
|
+
def search: (
|
|
11
|
+
String query,
|
|
12
|
+
?search_depth: String?,
|
|
13
|
+
?topic: String?,
|
|
14
|
+
?max_results: Integer?,
|
|
15
|
+
?chunks_per_source: Integer?,
|
|
16
|
+
?time_range: String?,
|
|
17
|
+
?days: Integer?,
|
|
18
|
+
?start_date: String?,
|
|
19
|
+
?end_date: String?,
|
|
20
|
+
?include_answer: (bool | String)?,
|
|
21
|
+
?include_raw_content: (bool | String)?,
|
|
22
|
+
?include_images: bool?,
|
|
23
|
+
?include_image_descriptions: bool?,
|
|
24
|
+
?include_favicon: bool?,
|
|
25
|
+
?include_domains: Array[String]?,
|
|
26
|
+
?exclude_domains: Array[String]?,
|
|
27
|
+
?country: String?,
|
|
28
|
+
?auto_parameters: bool?,
|
|
29
|
+
?include_usage: bool?,
|
|
30
|
+
**untyped extra
|
|
31
|
+
) -> SearchResponse
|
|
32
|
+
|
|
33
|
+
def qna_search: (String query, **untyped options) -> String?
|
|
34
|
+
|
|
35
|
+
def search_context: (String query, ?max_tokens: Integer, **untyped options) -> String
|
|
36
|
+
|
|
37
|
+
def extract: (
|
|
38
|
+
String | Array[String] urls,
|
|
39
|
+
?query: String?,
|
|
40
|
+
?chunks_per_source: Integer?,
|
|
41
|
+
?extract_depth: String?,
|
|
42
|
+
?include_images: bool?,
|
|
43
|
+
?include_favicon: bool?,
|
|
44
|
+
?format: String?,
|
|
45
|
+
?timeout: Numeric?,
|
|
46
|
+
?include_usage: bool?,
|
|
47
|
+
**untyped extra
|
|
48
|
+
) -> ExtractResponse
|
|
49
|
+
|
|
50
|
+
def crawl: (
|
|
51
|
+
String url,
|
|
52
|
+
?instructions: String?,
|
|
53
|
+
?chunks_per_source: Integer?,
|
|
54
|
+
?max_depth: Integer?,
|
|
55
|
+
?max_breadth: Integer?,
|
|
56
|
+
?limit: Integer?,
|
|
57
|
+
?select_paths: Array[String]?,
|
|
58
|
+
?select_domains: Array[String]?,
|
|
59
|
+
?exclude_paths: Array[String]?,
|
|
60
|
+
?exclude_domains: Array[String]?,
|
|
61
|
+
?allow_external: bool?,
|
|
62
|
+
?include_images: bool?,
|
|
63
|
+
?extract_depth: String?,
|
|
64
|
+
?format: String?,
|
|
65
|
+
?include_favicon: bool?,
|
|
66
|
+
?timeout: Numeric?,
|
|
67
|
+
?include_usage: bool?,
|
|
68
|
+
**untyped extra
|
|
69
|
+
) -> CrawlResponse
|
|
70
|
+
|
|
71
|
+
def map: (
|
|
72
|
+
String url,
|
|
73
|
+
?instructions: String?,
|
|
74
|
+
?max_depth: Integer?,
|
|
75
|
+
?max_breadth: Integer?,
|
|
76
|
+
?limit: Integer?,
|
|
77
|
+
?select_paths: Array[String]?,
|
|
78
|
+
?select_domains: Array[String]?,
|
|
79
|
+
?exclude_paths: Array[String]?,
|
|
80
|
+
?exclude_domains: Array[String]?,
|
|
81
|
+
?allow_external: bool?,
|
|
82
|
+
?timeout: Numeric?,
|
|
83
|
+
?include_usage: bool?,
|
|
84
|
+
**untyped extra
|
|
85
|
+
) -> MapResponse
|
|
86
|
+
|
|
87
|
+
def research: (
|
|
88
|
+
String input,
|
|
89
|
+
?model: String?,
|
|
90
|
+
?output_schema: Hash[untyped, untyped]?,
|
|
91
|
+
?citation_format: String?,
|
|
92
|
+
?include_domains: Array[String]?,
|
|
93
|
+
?exclude_domains: Array[String]?,
|
|
94
|
+
?output_length: String?,
|
|
95
|
+
?files: Array[Hash[untyped, untyped]]?,
|
|
96
|
+
**untyped extra
|
|
97
|
+
) ?{ (ResearchEvent) -> void } -> ResearchTask?
|
|
98
|
+
|
|
99
|
+
def research_task: (String request_id) -> ResearchTask
|
|
100
|
+
|
|
101
|
+
def wait_for_research: (
|
|
102
|
+
String request_id,
|
|
103
|
+
?poll_interval: Numeric,
|
|
104
|
+
?timeout: Numeric
|
|
105
|
+
) ?{ (ResearchTask) -> void } -> ResearchTask
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Tavily
|
|
2
|
+
class Configuration
|
|
3
|
+
DEFAULT_BASE_URL: String
|
|
4
|
+
DEFAULT_TIMEOUT: Integer
|
|
5
|
+
DEFAULT_OPEN_TIMEOUT: Integer
|
|
6
|
+
DEFAULT_MAX_RETRIES: Integer
|
|
7
|
+
DEFAULT_RETRY_BASE_DELAY: Float
|
|
8
|
+
|
|
9
|
+
attr_accessor api_key: String?
|
|
10
|
+
attr_accessor base_url: String
|
|
11
|
+
attr_accessor timeout: Numeric
|
|
12
|
+
attr_accessor open_timeout: Numeric
|
|
13
|
+
attr_accessor max_retries: Integer
|
|
14
|
+
attr_accessor retry_base_delay: Numeric
|
|
15
|
+
attr_accessor proxy: String?
|
|
16
|
+
attr_accessor ca_file: String?
|
|
17
|
+
attr_accessor logger: untyped
|
|
18
|
+
attr_accessor user_agent: String
|
|
19
|
+
|
|
20
|
+
def initialize: () -> void
|
|
21
|
+
def to_h: () -> Hash[Symbol, untyped]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module Tavily
|
|
2
|
+
class Connection
|
|
3
|
+
RETRIABLE_STATUSES: Array[Integer]
|
|
4
|
+
RETRIABLE_TIMEOUTS: Array[Class]
|
|
5
|
+
RETRIABLE_NETWORK: Array[Class]
|
|
6
|
+
|
|
7
|
+
def initialize: (Configuration config) -> void
|
|
8
|
+
def post: (String path, ?Hash[untyped, untyped] body) -> untyped
|
|
9
|
+
def get: (String path, ?Hash[untyped, untyped] params) -> untyped
|
|
10
|
+
def stream: (String path, ?Hash[untyped, untyped] body) { (ResearchEvent) -> void } -> nil
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Tavily
|
|
2
|
+
class Error < StandardError
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
class ConfigurationError < Error
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class TimeoutError < Error
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class ConnectionError < Error
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class APIError < Error
|
|
15
|
+
attr_reader status: Integer?
|
|
16
|
+
attr_reader body: untyped
|
|
17
|
+
attr_reader request_id: String?
|
|
18
|
+
|
|
19
|
+
def initialize: (?String? message, ?status: Integer?, ?body: untyped, ?request_id: String?) -> void
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class BadRequestError < APIError
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class AuthenticationError < APIError
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class ForbiddenError < APIError
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class NotFoundError < APIError
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class UnprocessableEntityError < APIError
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class RateLimitError < APIError
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class UsageLimitError < APIError
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class PlanLimitError < UsageLimitError
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class PayAsYouGoLimitError < UsageLimitError
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
class ServerError < APIError
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
module Errors
|
|
53
|
+
STATUS_MAP: Hash[Integer, Class]
|
|
54
|
+
|
|
55
|
+
def self.class_for: (Integer status) -> Class
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Tavily
|
|
2
|
+
class Object
|
|
3
|
+
attr_reader attributes: Hash[String, untyped]
|
|
4
|
+
|
|
5
|
+
def self.attribute: (Symbol name, ?key: String, ?wrap: (Class | String)?, ?collection: bool) -> void
|
|
6
|
+
|
|
7
|
+
def initialize: (?untyped attributes) -> void
|
|
8
|
+
def []: (String | Symbol key) -> untyped
|
|
9
|
+
def dig: (*(String | Symbol) keys) -> untyped
|
|
10
|
+
def key?: (String | Symbol key) -> bool
|
|
11
|
+
def to_h: () -> Hash[String, untyped]
|
|
12
|
+
def to_hash: () -> Hash[String, untyped]
|
|
13
|
+
def ==: (untyped other) -> bool
|
|
14
|
+
def eql?: (untyped other) -> bool
|
|
15
|
+
def hash: () -> Integer
|
|
16
|
+
def inspect: () -> String
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
module Tavily
|
|
2
|
+
class Usage < Object
|
|
3
|
+
def credits: () -> Integer?
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
class Image < Object
|
|
7
|
+
def url: () -> String?
|
|
8
|
+
def description: () -> String?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class SearchResult < Object
|
|
12
|
+
def title: () -> String?
|
|
13
|
+
def url: () -> String?
|
|
14
|
+
def content: () -> String?
|
|
15
|
+
def score: () -> Float?
|
|
16
|
+
def raw_content: () -> String?
|
|
17
|
+
def favicon: () -> String?
|
|
18
|
+
def published_date: () -> String?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
module Envelope
|
|
22
|
+
def self.included: (untyped base) -> void
|
|
23
|
+
|
|
24
|
+
def response_time: () -> Numeric?
|
|
25
|
+
def request_id: () -> String?
|
|
26
|
+
def usage: () -> Usage?
|
|
27
|
+
def credits: () -> Integer?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class SearchResponse < Object
|
|
31
|
+
include Envelope
|
|
32
|
+
|
|
33
|
+
def query: () -> String?
|
|
34
|
+
def answer: () -> String?
|
|
35
|
+
def follow_up_questions: () -> Array[untyped]?
|
|
36
|
+
def auto_parameters: () -> Hash[String, untyped]?
|
|
37
|
+
def results: () -> Array[SearchResult]
|
|
38
|
+
def images: () -> Array[Image]
|
|
39
|
+
def urls: () -> Array[String?]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class ExtractResult < Object
|
|
43
|
+
def url: () -> String?
|
|
44
|
+
def raw_content: () -> String?
|
|
45
|
+
def images: () -> Array[String]?
|
|
46
|
+
def favicon: () -> String?
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
class FailedResult < Object
|
|
50
|
+
def url: () -> String?
|
|
51
|
+
def error: () -> String?
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class ExtractResponse < Object
|
|
55
|
+
include Envelope
|
|
56
|
+
|
|
57
|
+
def results: () -> Array[ExtractResult]
|
|
58
|
+
def failed_results: () -> Array[FailedResult]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class CrawlResult < Object
|
|
62
|
+
def url: () -> String?
|
|
63
|
+
def raw_content: () -> String?
|
|
64
|
+
def favicon: () -> String?
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class CrawlResponse < Object
|
|
68
|
+
include Envelope
|
|
69
|
+
|
|
70
|
+
def base_url: () -> String?
|
|
71
|
+
def results: () -> Array[CrawlResult]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
class MapResponse < Object
|
|
75
|
+
include Envelope
|
|
76
|
+
|
|
77
|
+
def base_url: () -> String?
|
|
78
|
+
def results: () -> Array[String]?
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
class ResearchSource < Object
|
|
82
|
+
def title: () -> String?
|
|
83
|
+
def url: () -> String?
|
|
84
|
+
def favicon: () -> String?
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
class ResearchTask < Object
|
|
88
|
+
include Envelope
|
|
89
|
+
|
|
90
|
+
def request_id: () -> String?
|
|
91
|
+
def created_at: () -> String?
|
|
92
|
+
def status: () -> String?
|
|
93
|
+
def input: () -> String?
|
|
94
|
+
def model: () -> String?
|
|
95
|
+
def content: () -> (String | Hash[String, untyped])?
|
|
96
|
+
def sources: () -> Array[ResearchSource]
|
|
97
|
+
def completed?: () -> bool
|
|
98
|
+
def failed?: () -> bool
|
|
99
|
+
def pending?: () -> bool
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
class ResearchEvent
|
|
103
|
+
attr_accessor event: String?
|
|
104
|
+
attr_accessor data: untyped
|
|
105
|
+
|
|
106
|
+
def self.new: (?event: String?, ?data: untyped) -> instance
|
|
107
|
+
end
|
|
108
|
+
end
|
data/sig/tavily.rbs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Tavily
|
|
2
|
+
VERSION: String
|
|
3
|
+
|
|
4
|
+
def self.configuration: () -> Configuration
|
|
5
|
+
def self.configure: () ?{ (Configuration) -> void } -> Configuration
|
|
6
|
+
def self.reset_configuration!: () -> Configuration
|
|
7
|
+
def self.default_client: () -> Client
|
|
8
|
+
def self.reset_default_client!: () -> void
|
|
9
|
+
|
|
10
|
+
def self.search: (*untyped, **untyped) -> SearchResponse
|
|
11
|
+
def self.qna_search: (*untyped, **untyped) -> String?
|
|
12
|
+
def self.search_context: (*untyped, **untyped) -> String
|
|
13
|
+
def self.extract: (*untyped, **untyped) -> ExtractResponse
|
|
14
|
+
def self.crawl: (*untyped, **untyped) -> CrawlResponse
|
|
15
|
+
def self.map: (*untyped, **untyped) -> MapResponse
|
|
16
|
+
def self.research: (*untyped, **untyped) ?{ (ResearchEvent) -> void } -> ResearchTask?
|
|
17
|
+
def self.research_task: (*untyped, **untyped) -> ResearchTask
|
|
18
|
+
def self.wait_for_research: (*untyped, **untyped) ?{ (ResearchTask) -> void } -> ResearchTask
|
|
19
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: tavily
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- ned
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: |-
|
|
13
|
+
A lightweight, dependency-free Ruby client for the Tavily API. The web access
|
|
14
|
+
layer built for LLMs and AI agents. Wraps the search, extract, crawl, map, and
|
|
15
|
+
research endpoints with typed response objects, automatic retries with backoff,
|
|
16
|
+
streaming research, and granular error handling.
|
|
17
|
+
executables: []
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- CHANGELOG.md
|
|
22
|
+
- LICENSE.txt
|
|
23
|
+
- README.md
|
|
24
|
+
- lib/tavily.rb
|
|
25
|
+
- lib/tavily/client.rb
|
|
26
|
+
- lib/tavily/configuration.rb
|
|
27
|
+
- lib/tavily/connection.rb
|
|
28
|
+
- lib/tavily/errors.rb
|
|
29
|
+
- lib/tavily/object.rb
|
|
30
|
+
- lib/tavily/responses.rb
|
|
31
|
+
- lib/tavily/version.rb
|
|
32
|
+
- sig/tavily.rbs
|
|
33
|
+
- sig/tavily/client.rbs
|
|
34
|
+
- sig/tavily/configuration.rbs
|
|
35
|
+
- sig/tavily/connection.rbs
|
|
36
|
+
- sig/tavily/errors.rbs
|
|
37
|
+
- sig/tavily/object.rbs
|
|
38
|
+
- sig/tavily/responses.rbs
|
|
39
|
+
homepage: https://github.com/main-path/tavily
|
|
40
|
+
licenses:
|
|
41
|
+
- MIT
|
|
42
|
+
metadata:
|
|
43
|
+
source_code_uri: https://github.com/main-path/tavily
|
|
44
|
+
changelog_uri: https://github.com/main-path/tavily/blob/main/CHANGELOG.md
|
|
45
|
+
documentation_uri: https://docs.tavily.com/
|
|
46
|
+
bug_tracker_uri: https://github.com/main-path/tavily/issues
|
|
47
|
+
rubygems_mfa_required: 'true'
|
|
48
|
+
rdoc_options: []
|
|
49
|
+
require_paths:
|
|
50
|
+
- lib
|
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
52
|
+
requirements:
|
|
53
|
+
- - ">="
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: 3.1.0
|
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
requirements: []
|
|
62
|
+
rubygems_version: 3.6.9
|
|
63
|
+
specification_version: 4
|
|
64
|
+
summary: Ruby client for the Tavily search, extract, crawl, map, and research API.
|
|
65
|
+
test_files: []
|