exa-ai 0.3.0 → 0.3.1
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 +4 -4
- data/README.md +45 -583
- data/exe/exa-ai +1 -3
- data/exe/exa-ai-answer +1 -5
- data/exe/exa-ai-context +1 -4
- data/exe/exa-ai-get-contents +1 -4
- data/exe/exa-ai-research-get +1 -2
- data/exe/exa-ai-research-list +1 -2
- data/exe/exa-ai-research-start +1 -3
- data/exe/exa-ai-search +1 -3
- data/lib/exa/cli/base.rb +3 -3
- data/lib/exa/client.rb +1 -0
- data/lib/exa/connection.rb +8 -1
- data/lib/exa/version.rb +1 -1
- data/lib/exa-ai.rb +5 -0
- data/lib/exa.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6a7200f1be7297291b6fa6ecddfb0e87d49a9ef570a6bb73c00b7993a459daea
|
|
4
|
+
data.tar.gz: ac3a183a8ac848007659ab36cc759780e9724c9f2fdc5159b149eaf0633402af
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1dff4bc2b63bf920a8b732c4c0f465566fab48c066d1cb9ebc1e6f7f779ee86a780225ac96197d835296c1e780ee914cde34e60cd6f83a04af805f82692d9019
|
|
7
|
+
data.tar.gz: 015e85d8c37a4731c170e57129f997a3ff4960e1464aaecc5a42c4ac45d43a475b628ee776a1c6f28d32fa74b73c1bdab5d32e9b66385cb673bce3c7ca09532a
|
data/README.md
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# exa-ruby
|
|
2
2
|
|
|
3
|
-
Ruby client for the Exa.ai API
|
|
4
|
-
|
|
5
|
-
**Status**: Phase 9 CLI implementation complete. All commands working with full option support.
|
|
3
|
+
Ruby client for the Exa.ai API. Search and analyze web content using neural search, question answering, code discovery, and research automation.
|
|
6
4
|
|
|
7
5
|
## Installation
|
|
8
6
|
|
|
@@ -26,20 +24,18 @@ gem install exa-ai
|
|
|
26
24
|
|
|
27
25
|
## Configuration
|
|
28
26
|
|
|
29
|
-
### Setting Your API Key
|
|
30
|
-
|
|
31
27
|
Get your API key from [dashboard.exa.ai](https://dashboard.exa.ai).
|
|
32
28
|
|
|
33
|
-
**
|
|
29
|
+
**Environment Variable (recommended)**
|
|
34
30
|
|
|
35
31
|
```bash
|
|
36
32
|
export EXA_API_KEY="your-api-key-here"
|
|
37
33
|
```
|
|
38
34
|
|
|
39
|
-
**
|
|
35
|
+
**Ruby Code**
|
|
40
36
|
|
|
41
37
|
```ruby
|
|
42
|
-
require 'exa'
|
|
38
|
+
require 'exa-ai'
|
|
43
39
|
|
|
44
40
|
Exa.configure do |config|
|
|
45
41
|
config.api_key = "your-api-key-here"
|
|
@@ -49,18 +45,18 @@ end
|
|
|
49
45
|
client = Exa::Client.new(api_key: "your-api-key-here")
|
|
50
46
|
```
|
|
51
47
|
|
|
52
|
-
**
|
|
48
|
+
**CLI Flag**
|
|
53
49
|
|
|
54
50
|
```bash
|
|
55
51
|
exa-ai search "query" --api-key YOUR_API_KEY
|
|
56
52
|
```
|
|
57
53
|
|
|
58
|
-
##
|
|
54
|
+
## Quick Start
|
|
59
55
|
|
|
60
|
-
###
|
|
56
|
+
### Ruby API
|
|
61
57
|
|
|
62
58
|
```ruby
|
|
63
|
-
require 'exa'
|
|
59
|
+
require 'exa-ai'
|
|
64
60
|
|
|
65
61
|
Exa.configure do |config|
|
|
66
62
|
config.api_key = ENV['EXA_API_KEY']
|
|
@@ -70,626 +66,92 @@ client = Exa::Client.new
|
|
|
70
66
|
|
|
71
67
|
# Search the web
|
|
72
68
|
results = client.search("ruby programming")
|
|
73
|
-
|
|
69
|
+
results.results.each { |item| puts "#{item['title']}: #{item['url']}" }
|
|
74
70
|
|
|
75
71
|
# Get an answer to a question
|
|
76
72
|
answer = client.answer("What are the latest trends in AI?")
|
|
77
73
|
puts answer.answer
|
|
78
|
-
puts answer.citations
|
|
79
74
|
|
|
80
|
-
#
|
|
75
|
+
# Find code examples
|
|
81
76
|
code = client.context("React hooks")
|
|
82
77
|
puts code.response
|
|
83
78
|
|
|
84
|
-
#
|
|
79
|
+
# Get page contents
|
|
85
80
|
contents = client.get_contents(["https://example.com"])
|
|
86
81
|
puts contents.results.first["text"]
|
|
87
82
|
```
|
|
88
83
|
|
|
89
|
-
###
|
|
90
|
-
|
|
91
|
-
```ruby
|
|
92
|
-
client = Exa::Client.new(api_key: "your-key")
|
|
93
|
-
|
|
94
|
-
# Basic search
|
|
95
|
-
results = client.search("machine learning")
|
|
96
|
-
|
|
97
|
-
# With options
|
|
98
|
-
results = client.search("AI",
|
|
99
|
-
num_results: 10,
|
|
100
|
-
type: "neural",
|
|
101
|
-
include_domains: ["arxiv.org", "github.com"]
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
# Access results
|
|
105
|
-
results.results.each do |item|
|
|
106
|
-
puts item["title"]
|
|
107
|
-
puts item["url"]
|
|
108
|
-
puts item["score"]
|
|
109
|
-
end
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### Answer
|
|
113
|
-
|
|
114
|
-
```ruby
|
|
115
|
-
client = Exa::Client.new(api_key: "your-key")
|
|
116
|
-
|
|
117
|
-
# Get an answer to a question
|
|
118
|
-
answer = client.answer("What are the best practices for API design?")
|
|
119
|
-
|
|
120
|
-
puts answer.answer # The generated answer
|
|
121
|
-
puts answer.citations # Array of source citations
|
|
122
|
-
puts answer.cost_dollars # API cost
|
|
123
|
-
|
|
124
|
-
# With text content from sources
|
|
125
|
-
answer = client.answer("Latest AI breakthroughs", text: true)
|
|
126
|
-
puts answer.answer
|
|
127
|
-
answer.citations.each do |citation|
|
|
128
|
-
puts "#{citation["title"]} (#{citation['url']})"
|
|
129
|
-
end
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### Context (Code Search)
|
|
133
|
-
|
|
134
|
-
```ruby
|
|
135
|
-
code = client.context("authentication in Rails")
|
|
136
|
-
|
|
137
|
-
puts code.response # The code context
|
|
138
|
-
puts code.results_count # Number of results
|
|
139
|
-
puts code.cost_dollars # API cost
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### Get Contents
|
|
143
|
-
|
|
144
|
-
```ruby
|
|
145
|
-
contents = client.get_contents([
|
|
146
|
-
"https://example.com/page1",
|
|
147
|
-
"https://example.com/page2"
|
|
148
|
-
])
|
|
149
|
-
|
|
150
|
-
contents.results.each do |content|
|
|
151
|
-
puts content["url"]
|
|
152
|
-
puts content["title"]
|
|
153
|
-
puts content["text"]
|
|
154
|
-
end
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
### Research (Async Tasks)
|
|
158
|
-
|
|
159
|
-
```ruby
|
|
160
|
-
# Start a research task
|
|
161
|
-
task = client.research_start(
|
|
162
|
-
instructions: "Analyze recent AI breakthroughs",
|
|
163
|
-
model: "gpt-4"
|
|
164
|
-
)
|
|
165
|
-
puts task.research_id # Save for later polling
|
|
166
|
-
|
|
167
|
-
# Check status
|
|
168
|
-
status = client.research_get(task.research_id)
|
|
169
|
-
if status.completed?
|
|
170
|
-
puts status.output
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
# List all tasks
|
|
174
|
-
list = client.research_list(limit: 20)
|
|
175
|
-
list.data.each do |task|
|
|
176
|
-
puts "#{task.research_id}: #{task.status}"
|
|
177
|
-
end
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## CLI Usage
|
|
181
|
-
|
|
182
|
-
### Main Commands
|
|
183
|
-
|
|
184
|
-
```bash
|
|
185
|
-
exa-ai <command> [options]
|
|
186
|
-
|
|
187
|
-
Commands:
|
|
188
|
-
search Search the web
|
|
189
|
-
answer Generate answers to questions
|
|
190
|
-
context Get code context from repositories
|
|
191
|
-
get-contents Retrieve page contents
|
|
192
|
-
research-start Start a research task
|
|
193
|
-
research-get Get research task status
|
|
194
|
-
research-list List research tasks
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
### Search Command
|
|
198
|
-
|
|
199
|
-
Search the web using Exa's neural search:
|
|
84
|
+
### Command Line
|
|
200
85
|
|
|
201
86
|
```bash
|
|
202
|
-
#
|
|
87
|
+
# Search the web
|
|
203
88
|
exa-ai search "ruby programming"
|
|
204
89
|
|
|
205
|
-
#
|
|
206
|
-
exa-ai
|
|
207
|
-
|
|
208
|
-
# Filter by domains
|
|
209
|
-
exa-ai search "tutorials" \
|
|
210
|
-
--include-domains "github.com,dev.to" \
|
|
211
|
-
--exclude-domains "outdated-site.com"
|
|
212
|
-
|
|
213
|
-
# Pretty output
|
|
214
|
-
exa-ai search "AI" --output-format pretty
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
**Basic Options:**
|
|
218
|
-
- `QUERY` - Search query (required)
|
|
219
|
-
- `--num-results N` - Number of results (default: 10)
|
|
220
|
-
- `--type TYPE` - Search type: keyword, neural, or auto (default: auto)
|
|
221
|
-
- `--include-domains DOMAINS` - Comma-separated domains to include
|
|
222
|
-
- `--exclude-domains DOMAINS` - Comma-separated domains to exclude
|
|
223
|
-
- `--output-format FORMAT` - json or pretty (default: json)
|
|
224
|
-
- `--api-key KEY` - API key (or set EXA_API_KEY env var)
|
|
225
|
-
|
|
226
|
-
#### Advanced Search Options
|
|
227
|
-
|
|
228
|
-
**Date Filtering:**
|
|
229
|
-
```bash
|
|
230
|
-
# Filter by published date
|
|
231
|
-
exa-ai search "AI research" \
|
|
232
|
-
--start-published-date "2025-01-01T00:00:00.000Z" \
|
|
233
|
-
--end-published-date "2025-12-31T23:59:59.999Z"
|
|
234
|
-
|
|
235
|
-
# Filter by crawl date
|
|
236
|
-
exa-ai search "news" \
|
|
237
|
-
--start-crawl-date "2025-10-01T00:00:00.000Z" \
|
|
238
|
-
--end-crawl-date "2025-10-31T23:59:59.999Z"
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
**Text Filtering:**
|
|
242
|
-
```bash
|
|
243
|
-
# Results must include specific phrase
|
|
244
|
-
exa-ai search "machine learning" --include-text "neural networks"
|
|
245
|
-
|
|
246
|
-
# Results must exclude specific phrase
|
|
247
|
-
exa-ai search "programming" --exclude-text "paid-partnership"
|
|
248
|
-
|
|
249
|
-
# Combine inclusion and exclusion
|
|
250
|
-
exa-ai search "Python" \
|
|
251
|
-
--include-text "open source" \
|
|
252
|
-
--exclude-text "deprecated"
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
**Content Extraction:**
|
|
256
|
-
```bash
|
|
257
|
-
# Extract full webpage text
|
|
258
|
-
exa-ai search "Ruby" --text
|
|
259
|
-
|
|
260
|
-
# Extract text with options
|
|
261
|
-
exa-ai search "AI" \
|
|
262
|
-
--text \
|
|
263
|
-
--text-max-characters 3000 \
|
|
264
|
-
--include-html-tags
|
|
265
|
-
|
|
266
|
-
# Generate AI summaries
|
|
267
|
-
exa-ai search "climate change" \
|
|
268
|
-
--summary \
|
|
269
|
-
--summary-query "What are the main points?"
|
|
270
|
-
|
|
271
|
-
# Format results as context for LLM RAG
|
|
272
|
-
exa-ai search "kubernetes" \
|
|
273
|
-
--context \
|
|
274
|
-
--context-max-characters 5000
|
|
275
|
-
|
|
276
|
-
# Crawl subpages
|
|
277
|
-
exa-ai search "documentation" \
|
|
278
|
-
--subpages 1 \
|
|
279
|
-
--subpage-target about \
|
|
280
|
-
--subpage-target docs
|
|
281
|
-
|
|
282
|
-
# Extract links from results
|
|
283
|
-
exa-ai search "web development" \
|
|
284
|
-
--links 3 \
|
|
285
|
-
--image-links 2
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
**Advanced Ruby API:**
|
|
289
|
-
```ruby
|
|
290
|
-
client = Exa::Client.new(api_key: "your-key")
|
|
291
|
-
|
|
292
|
-
# Date range filtering
|
|
293
|
-
results = client.search("AI research",
|
|
294
|
-
start_published_date: "2025-01-01T00:00:00.000Z",
|
|
295
|
-
end_published_date: "2025-12-31T23:59:59.999Z"
|
|
296
|
-
)
|
|
297
|
-
|
|
298
|
-
# Text filtering
|
|
299
|
-
results = client.search("machine learning",
|
|
300
|
-
include_text: ["neural networks"],
|
|
301
|
-
exclude_text: ["cryptocurrency"]
|
|
302
|
-
)
|
|
303
|
-
|
|
304
|
-
# Full webpage text extraction
|
|
305
|
-
results = client.search("Ruby",
|
|
306
|
-
text: {
|
|
307
|
-
max_characters: 3000,
|
|
308
|
-
include_html_tags: true
|
|
309
|
-
}
|
|
310
|
-
)
|
|
311
|
-
|
|
312
|
-
# AI-powered summaries
|
|
313
|
-
results = client.search("climate change",
|
|
314
|
-
summary: {
|
|
315
|
-
query: "What are the main points?"
|
|
316
|
-
}
|
|
317
|
-
)
|
|
318
|
-
|
|
319
|
-
# Context for RAG pipelines
|
|
320
|
-
results = client.search("kubernetes",
|
|
321
|
-
context: {
|
|
322
|
-
max_characters: 5000
|
|
323
|
-
}
|
|
324
|
-
)
|
|
325
|
-
|
|
326
|
-
# Subpage crawling
|
|
327
|
-
results = client.search("documentation",
|
|
328
|
-
subpages: 1,
|
|
329
|
-
subpage_target: ["about", "docs", "guide"]
|
|
330
|
-
)
|
|
331
|
-
|
|
332
|
-
# Links and image extraction
|
|
333
|
-
results = client.search("web development",
|
|
334
|
-
extras: {
|
|
335
|
-
links: 3,
|
|
336
|
-
image_links: 2
|
|
337
|
-
}
|
|
338
|
-
)
|
|
339
|
-
|
|
340
|
-
# Combine multiple features
|
|
341
|
-
results = client.search("AI",
|
|
342
|
-
num_results: 5,
|
|
343
|
-
start_published_date: "2025-01-01T00:00:00.000Z",
|
|
344
|
-
text: { max_characters: 3000 },
|
|
345
|
-
summary: { query: "Main developments?" },
|
|
346
|
-
context: { max_characters: 5000 },
|
|
347
|
-
subpages: 1,
|
|
348
|
-
subpage_target: ["research"],
|
|
349
|
-
extras: { links: 3, image_links: 2 }
|
|
350
|
-
)
|
|
351
|
-
|
|
352
|
-
# Access extracted content
|
|
353
|
-
results.results.each do |result|
|
|
354
|
-
puts result["title"]
|
|
355
|
-
puts result["text"] if result["text"] # Full webpage text
|
|
356
|
-
puts result["summary"] if result["summary"] # AI summary
|
|
357
|
-
puts result["links"] if result["links"] # Extracted links
|
|
358
|
-
end
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
### Answer Command
|
|
362
|
-
|
|
363
|
-
Generate comprehensive answers to questions using Exa's answer generation feature:
|
|
364
|
-
|
|
365
|
-
```bash
|
|
366
|
-
# Basic question
|
|
367
|
-
exa-ai answer "What is the capital of France?"
|
|
368
|
-
|
|
369
|
-
# Get answer with source citations
|
|
370
|
-
exa-ai answer "Latest developments in quantum computing"
|
|
371
|
-
|
|
372
|
-
# Include full text from sources
|
|
373
|
-
exa-ai answer "Ruby on Rails best practices" --text
|
|
374
|
-
|
|
375
|
-
# Pretty formatted output
|
|
376
|
-
exa-ai answer "How do I learn machine learning?" --output-format pretty
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
**Options:**
|
|
380
|
-
- `QUERY` - Question to answer (required)
|
|
381
|
-
- `--text` - Include full text content from source pages
|
|
382
|
-
- `--output-format FORMAT` - json or pretty (default: json)
|
|
383
|
-
- `--api-key KEY` - API key (or set EXA_API_KEY env var)
|
|
384
|
-
|
|
385
|
-
**Response fields:**
|
|
386
|
-
- `answer` - The generated answer to your question
|
|
387
|
-
- `citations` - Array of source citations with URLs
|
|
388
|
-
- `cost_dollars` - Cost of the API request
|
|
389
|
-
|
|
390
|
-
### Context Command (Code Search)
|
|
391
|
-
|
|
392
|
-
Find code snippets and context from open-source repositories:
|
|
393
|
-
|
|
394
|
-
```bash
|
|
395
|
-
# Basic query
|
|
396
|
-
exa-ai context "authentication with JWT"
|
|
397
|
-
|
|
398
|
-
# With custom token allocation
|
|
399
|
-
exa-ai context "React hooks" --tokens-num 5000
|
|
400
|
-
|
|
401
|
-
# Text output
|
|
402
|
-
exa-ai context "async/await patterns" --output-format text
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
**Options:**
|
|
406
|
-
- `QUERY` - Search query (required)
|
|
407
|
-
- `--tokens-num NUM` - Token allocation, integer or "dynamic" (default: dynamic)
|
|
408
|
-
- `--output-format FORMAT` - json or text (default: json)
|
|
409
|
-
- `--api-key KEY` - API key
|
|
410
|
-
|
|
411
|
-
### Get-Contents Command
|
|
412
|
-
|
|
413
|
-
Retrieve the full text content from web pages:
|
|
90
|
+
# Answer a question
|
|
91
|
+
exa-ai answer "What is machine learning?"
|
|
414
92
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
exa-ai get-contents "https://example.com/article"
|
|
418
|
-
|
|
419
|
-
# Multiple pages (comma-separated)
|
|
420
|
-
exa-ai get-contents "https://site1.com,https://site2.com"
|
|
421
|
-
|
|
422
|
-
# With options
|
|
423
|
-
exa-ai get-contents "id1,id2,id3" \
|
|
424
|
-
--text \
|
|
425
|
-
--highlights \
|
|
426
|
-
--output-format pretty
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
**Options:**
|
|
430
|
-
- `IDS` - Page IDs or URLs (required, comma-separated)
|
|
431
|
-
- `--text` - Include full text content
|
|
432
|
-
- `--highlights` - Include highlighted sections
|
|
433
|
-
- `--summary` - Include summary
|
|
434
|
-
- `--output-format FORMAT` - json or pretty (default: json)
|
|
435
|
-
- `--api-key KEY` - API key
|
|
436
|
-
|
|
437
|
-
### Research Commands
|
|
438
|
-
|
|
439
|
-
Start and manage long-running research tasks:
|
|
440
|
-
|
|
441
|
-
#### research-start
|
|
442
|
-
|
|
443
|
-
```bash
|
|
444
|
-
# Start a task
|
|
445
|
-
exa-ai research-start --instructions "Find Ruby performance tips"
|
|
446
|
-
|
|
447
|
-
# Start and wait for completion
|
|
448
|
-
exa-ai research-start \
|
|
449
|
-
--instructions "Analyze AI safety papers" \
|
|
450
|
-
--model gpt-4 \
|
|
451
|
-
--wait
|
|
452
|
-
|
|
453
|
-
# With output schema
|
|
454
|
-
exa-ai research-start \
|
|
455
|
-
--instructions "Extract key metrics" \
|
|
456
|
-
--output-schema '{"format":"json","fields":["metric","value"]}'
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
**Options:**
|
|
460
|
-
- `--instructions TEXT` - Research instructions (required)
|
|
461
|
-
- `--model MODEL` - Model to use (e.g., gpt-4)
|
|
462
|
-
- `--output-schema SCHEMA` - JSON schema for structured output
|
|
463
|
-
- `--wait` - Wait for task to complete (with polling)
|
|
464
|
-
- `--events` - Show event log during polling
|
|
465
|
-
- `--output-format FORMAT` - json or pretty (default: json)
|
|
466
|
-
- `--api-key KEY` - API key
|
|
467
|
-
|
|
468
|
-
#### research-get
|
|
469
|
-
|
|
470
|
-
```bash
|
|
471
|
-
# Check task status
|
|
472
|
-
exa-ai research-get abc-123
|
|
473
|
-
|
|
474
|
-
# With events
|
|
475
|
-
exa-ai research-get abc-123 --events
|
|
476
|
-
|
|
477
|
-
# Pretty output
|
|
478
|
-
exa-ai research-get abc-123 --output-format pretty
|
|
479
|
-
```
|
|
480
|
-
|
|
481
|
-
**Options:**
|
|
482
|
-
- `RESEARCH_ID` - Task ID (required)
|
|
483
|
-
- `--events` - Include event log
|
|
484
|
-
- `--stream` - Stream results (premium feature)
|
|
485
|
-
- `--output-format FORMAT` - json or pretty (default: json)
|
|
486
|
-
- `--api-key KEY` - API key
|
|
487
|
-
|
|
488
|
-
#### research-list
|
|
489
|
-
|
|
490
|
-
```bash
|
|
491
|
-
# List all tasks
|
|
492
|
-
exa-ai research-list
|
|
93
|
+
# Find code examples
|
|
94
|
+
exa-ai context "async/await error handling"
|
|
493
95
|
|
|
494
|
-
#
|
|
495
|
-
exa-ai
|
|
96
|
+
# Get page contents
|
|
97
|
+
exa-ai get-contents "https://example.com"
|
|
496
98
|
|
|
497
|
-
#
|
|
498
|
-
exa-ai research-
|
|
499
|
-
|
|
500
|
-
# Pretty table format
|
|
501
|
-
exa-ai research-list --output-format pretty
|
|
99
|
+
# Start a research task
|
|
100
|
+
exa-ai research-start --instructions "Analyze recent ML papers" --wait
|
|
502
101
|
```
|
|
503
102
|
|
|
504
|
-
|
|
505
|
-
- `--cursor CURSOR` - Pagination cursor
|
|
506
|
-
- `--limit N` - Results per page (default: 10)
|
|
507
|
-
- `--output-format FORMAT` - json or pretty (default: json)
|
|
508
|
-
- `--api-key KEY` - API key
|
|
509
|
-
|
|
510
|
-
### Global Options
|
|
103
|
+
## Features
|
|
511
104
|
|
|
512
|
-
|
|
513
|
-
- `--api-key KEY` - Override API key
|
|
514
|
-
- `--output-format FORMAT` - json, pretty, or text (varies by command)
|
|
515
|
-
- `--help, -h` - Show command help
|
|
516
|
-
- `exa-ai --version` - Show version
|
|
517
|
-
- `exa-ai --help` - Show available commands
|
|
105
|
+
The gem provides complete access to Exa's API endpoints:
|
|
518
106
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
**
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
# Returns formatted JSON object
|
|
525
|
-
```
|
|
526
|
-
|
|
527
|
-
**Pretty**
|
|
528
|
-
```bash
|
|
529
|
-
exa-ai search "ruby" --output-format pretty
|
|
530
|
-
# Returns human-readable format with titles, URLs, scores
|
|
531
|
-
```
|
|
532
|
-
|
|
533
|
-
**Text**
|
|
534
|
-
```bash
|
|
535
|
-
exa-ai context "React" --output-format text
|
|
536
|
-
# Returns plain text output
|
|
537
|
-
```
|
|
107
|
+
- **Search** — Neural and keyword search across billions of web pages
|
|
108
|
+
- **Answer** — Generate comprehensive answers with source citations
|
|
109
|
+
- **Context** — Find relevant code and documentation snippets
|
|
110
|
+
- **Get Contents** — Extract full text content from web pages
|
|
111
|
+
- **Research** — Start and manage long-running research tasks with AI
|
|
538
112
|
|
|
539
113
|
## Error Handling
|
|
540
114
|
|
|
541
|
-
The CLI provides helpful error messages:
|
|
542
|
-
|
|
543
|
-
```bash
|
|
544
|
-
# Missing API key
|
|
545
|
-
$ exa search "test"
|
|
546
|
-
❌ Configuration Error
|
|
547
|
-
|
|
548
|
-
Missing API key. Set EXA_API_KEY or use --api-key
|
|
549
|
-
|
|
550
|
-
Solutions:
|
|
551
|
-
1. Set the EXA_API_KEY environment variable:
|
|
552
|
-
export EXA_API_KEY='your-api-key'
|
|
553
|
-
...
|
|
554
|
-
|
|
555
|
-
# Invalid credentials
|
|
556
|
-
$ exa search "test" --api-key bad-key
|
|
557
|
-
❌ Authentication Error
|
|
558
|
-
|
|
559
|
-
Your API key is invalid or has expired.
|
|
560
|
-
...
|
|
561
|
-
|
|
562
|
-
# Rate limited
|
|
563
|
-
$ exa search "test" # After many requests
|
|
564
|
-
❌ Request Error
|
|
565
|
-
|
|
566
|
-
You've exceeded the rate limit. Please wait before trying again.
|
|
567
|
-
```
|
|
568
|
-
|
|
569
|
-
### Ruby API Error Handling
|
|
570
|
-
|
|
571
115
|
```ruby
|
|
572
|
-
|
|
116
|
+
require 'exa-ai'
|
|
117
|
+
|
|
118
|
+
client = Exa::Client.new(api_key: "your-key")
|
|
573
119
|
|
|
574
120
|
begin
|
|
575
121
|
results = client.search("test")
|
|
576
122
|
rescue Exa::Unauthorized => e
|
|
577
123
|
puts "Invalid API key: #{e.message}"
|
|
578
124
|
rescue Exa::TooManyRequests => e
|
|
579
|
-
puts "Rate limited, please
|
|
125
|
+
puts "Rate limited, please retry"
|
|
580
126
|
rescue Exa::ServerError => e
|
|
581
|
-
puts "
|
|
127
|
+
puts "Server error: #{e.message}"
|
|
582
128
|
end
|
|
583
129
|
```
|
|
584
130
|
|
|
585
|
-
##
|
|
586
|
-
|
|
587
|
-
### CLI Examples
|
|
588
|
-
|
|
589
|
-
```bash
|
|
590
|
-
# Find Ruby tutorials
|
|
591
|
-
exa search "Ruby best practices" --num-results 5
|
|
592
|
-
|
|
593
|
-
# Get an answer to a question
|
|
594
|
-
exa answer "What is machine learning?"
|
|
595
|
-
|
|
596
|
-
# Get code examples for async/await
|
|
597
|
-
exa context "async/await error handling"
|
|
598
|
-
|
|
599
|
-
# Research AI trends
|
|
600
|
-
exa research-start --instructions "What are latest AI trends?" --wait
|
|
601
|
-
|
|
602
|
-
# Retrieve and analyze multiple pages
|
|
603
|
-
exa get-contents "url1,url2,url3" --text --output-format pretty
|
|
604
|
-
```
|
|
605
|
-
|
|
606
|
-
### Ruby API Examples
|
|
607
|
-
|
|
608
|
-
```ruby
|
|
609
|
-
require 'exa'
|
|
610
|
-
|
|
611
|
-
Exa.configure do |config|
|
|
612
|
-
config.api_key = ENV['EXA_API_KEY']
|
|
613
|
-
end
|
|
614
|
-
|
|
615
|
-
client = Exa::Client.new
|
|
616
|
-
|
|
617
|
-
# Search with filtering
|
|
618
|
-
results = client.search("kubernetes tutorial",
|
|
619
|
-
num_results: 20,
|
|
620
|
-
type: "neural",
|
|
621
|
-
include_domains: ["kubernetes.io", "github.com"]
|
|
622
|
-
)
|
|
623
|
-
|
|
624
|
-
results.results.each do |item|
|
|
625
|
-
puts "#{item['title']} (#{item['url']})"
|
|
626
|
-
end
|
|
131
|
+
## Documentation
|
|
627
132
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
# Start async research
|
|
633
|
-
task = client.research_start(
|
|
634
|
-
instructions: "Summarize recent ML papers",
|
|
635
|
-
model: "gpt-4"
|
|
636
|
-
)
|
|
637
|
-
puts "Task started: #{task.research_id}"
|
|
638
|
-
|
|
639
|
-
# Poll for results
|
|
640
|
-
loop do
|
|
641
|
-
status = client.research_get(task.research_id)
|
|
642
|
-
break if status.completed? || status.failed?
|
|
643
|
-
sleep 5
|
|
644
|
-
end
|
|
645
|
-
|
|
646
|
-
if status.completed?
|
|
647
|
-
puts status.output
|
|
648
|
-
end
|
|
649
|
-
```
|
|
133
|
+
- **[Full Ruby API Documentation](./docs/API.md)** — All methods and parameters
|
|
134
|
+
- **[CLI Command Reference](./docs/CLI.md)** — All CLI commands and options
|
|
135
|
+
- **[Exa API Docs](https://docs.exa.ai)** — Exa API reference
|
|
650
136
|
|
|
651
137
|
## Development
|
|
652
138
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
# Run specific test file
|
|
660
|
-
bundle exec ruby test/cli/search_test.rb
|
|
661
|
-
|
|
662
|
-
# Run with verbose output
|
|
663
|
-
bundle exec rake test TESTOPTS="-v"
|
|
664
|
-
```
|
|
665
|
-
|
|
666
|
-
### Building the Gem
|
|
667
|
-
|
|
668
|
-
```bash
|
|
669
|
-
bundle exec rake build
|
|
670
|
-
bundle exec rake install
|
|
671
|
-
```
|
|
672
|
-
|
|
673
|
-
## Documentation
|
|
674
|
-
|
|
675
|
-
- [Exa API Documentation](https://docs.exa.ai)
|
|
676
|
-
- [API Reference](https://docs.exa.ai/reference)
|
|
677
|
-
- [Status Page](https://status.exa.ai)
|
|
139
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for:
|
|
140
|
+
- Running tests
|
|
141
|
+
- Development setup
|
|
142
|
+
- Code conventions
|
|
143
|
+
- Building and releasing
|
|
678
144
|
|
|
679
145
|
## Support
|
|
680
146
|
|
|
681
147
|
- **Documentation**: https://docs.exa.ai
|
|
682
|
-
- **
|
|
148
|
+
- **Dashboard**: https://dashboard.exa.ai
|
|
683
149
|
- **Status**: https://status.exa.ai
|
|
684
150
|
|
|
685
151
|
## License
|
|
686
152
|
|
|
687
|
-
MIT License - See LICENSE file for details
|
|
688
|
-
|
|
689
|
-
## Changelog
|
|
690
|
-
|
|
691
|
-
See [CHANGELOG.md](CHANGELOG.md) for version history and updates.
|
|
153
|
+
MIT License - See [LICENSE](LICENSE) file for details
|
|
692
154
|
|
|
693
155
|
---
|
|
694
156
|
|
|
695
|
-
**Built with Exa.ai**
|
|
157
|
+
**Built with [Exa.ai](https://exa.ai)** — The search and discovery API
|
data/exe/exa-ai
CHANGED
data/exe/exa-ai-answer
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
require "bundler/setup"
|
|
6
|
-
require "exa"
|
|
7
|
-
require "exa/cli/base"
|
|
8
|
-
require "exa/cli/formatters/answer_formatter"
|
|
4
|
+
require "exa-ai"
|
|
9
5
|
|
|
10
6
|
# Parse command-line arguments
|
|
11
7
|
def parse_args(argv)
|
data/exe/exa-ai-context
CHANGED
data/exe/exa-ai-get-contents
CHANGED
data/exe/exa-ai-research-get
CHANGED
data/exe/exa-ai-research-list
CHANGED
data/exe/exa-ai-research-start
CHANGED
data/exe/exa-ai-search
CHANGED
data/lib/exa/cli/base.rb
CHANGED
|
@@ -11,7 +11,7 @@ module Exa
|
|
|
11
11
|
env_key = ENV["EXA_API_KEY"]
|
|
12
12
|
return env_key if env_key && !env_key.empty?
|
|
13
13
|
|
|
14
|
-
raise ConfigurationError,
|
|
14
|
+
raise Exa::ConfigurationError,
|
|
15
15
|
"Missing API key. Set EXA_API_KEY environment variable or use --api-key flag"
|
|
16
16
|
end
|
|
17
17
|
|
|
@@ -24,13 +24,13 @@ module Exa
|
|
|
24
24
|
|
|
25
25
|
return format if valid_formats.include?(format)
|
|
26
26
|
|
|
27
|
-
raise ConfigurationError,
|
|
27
|
+
raise Exa::ConfigurationError,
|
|
28
28
|
"Invalid output format: #{format}. Valid formats: #{valid_formats.join(', ')}"
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
# Build a client instance with the given API key
|
|
32
32
|
def self.build_client(api_key, **options)
|
|
33
|
-
Client.new(api_key: api_key, **options)
|
|
33
|
+
Exa::Client.new(api_key: api_key, **options)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
# Format output data based on format type
|
data/lib/exa/client.rb
CHANGED
data/lib/exa/connection.rb
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "faraday"
|
|
4
|
+
require "logger"
|
|
4
5
|
|
|
5
6
|
module Exa
|
|
6
7
|
class Connection
|
|
8
|
+
DEFAULT_BASE_URL = "https://api.exa.ai"
|
|
7
9
|
def self.build(api_key:, **options, &block)
|
|
8
10
|
Faraday.new(url: options[:base_url] || DEFAULT_BASE_URL) do |conn|
|
|
9
11
|
# Authentication
|
|
10
|
-
conn.
|
|
12
|
+
conn.headers["x-api-key"] = api_key
|
|
11
13
|
|
|
12
14
|
# Request/Response JSON encoding
|
|
13
15
|
conn.request :json
|
|
14
16
|
|
|
17
|
+
# Debug logging (when enabled via option)
|
|
18
|
+
if options[:debug]
|
|
19
|
+
conn.response :logger, Logger.new($stdout), headers: true, bodies: true
|
|
20
|
+
end
|
|
21
|
+
|
|
15
22
|
# Custom error handling (registered before JSON so it runs after in response chain)
|
|
16
23
|
conn.response :raise_error
|
|
17
24
|
conn.response :json, content_type: /\bjson$/
|
data/lib/exa/version.rb
CHANGED
data/lib/exa-ai.rb
ADDED
data/lib/exa.rb
CHANGED
|
@@ -28,6 +28,7 @@ require_relative "exa/cli/formatters/search_formatter"
|
|
|
28
28
|
require_relative "exa/cli/formatters/context_formatter"
|
|
29
29
|
require_relative "exa/cli/formatters/contents_formatter"
|
|
30
30
|
require_relative "exa/cli/formatters/research_formatter"
|
|
31
|
+
require_relative "exa/cli/formatters/answer_formatter"
|
|
31
32
|
|
|
32
33
|
module Exa
|
|
33
34
|
# Module-level configuration
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: exa-ai
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Benjamin Jackson
|
|
@@ -132,6 +132,7 @@ files:
|
|
|
132
132
|
- exe/exa-ai-research-list
|
|
133
133
|
- exe/exa-ai-research-start
|
|
134
134
|
- exe/exa-ai-search
|
|
135
|
+
- lib/exa-ai.rb
|
|
135
136
|
- lib/exa.rb
|
|
136
137
|
- lib/exa/cli/base.rb
|
|
137
138
|
- lib/exa/cli/error_handler.rb
|