exa-ai 0.2.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.
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # exa-ruby
2
2
 
3
- Ruby client for the Exa.ai API with comprehensive command-line interface.
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
- **Option 1: Environment Variable (recommended)**
29
+ **Environment Variable (recommended)**
34
30
 
35
31
  ```bash
36
32
  export EXA_API_KEY="your-api-key-here"
37
33
  ```
38
34
 
39
- **Option 2: Ruby Code**
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
- **Option 3: CLI Flag**
48
+ **CLI Flag**
53
49
 
54
50
  ```bash
55
51
  exa-ai search "query" --api-key YOUR_API_KEY
56
52
  ```
57
53
 
58
- ## Ruby API Usage
54
+ ## Quick Start
59
55
 
60
- ### Quick Start
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,628 +66,92 @@ client = Exa::Client.new
70
66
 
71
67
  # Search the web
72
68
  results = client.search("ruby programming")
73
- puts results.results.first["title"]
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
- # Get code context
75
+ # Find code examples
81
76
  code = client.context("React hooks")
82
77
  puts code.response
83
78
 
84
- # Retrieve page contents
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
- ### Search
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
- # Basic search
87
+ # Search the web
203
88
  exa-ai search "ruby programming"
204
89
 
205
- # With options
206
- exa-ai search "machine learning" --num-results 10 --type keyword
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
- - `--use-autoprompt` - Use Exa's autoprompt feature
224
- - `--output-format FORMAT` - json or pretty (default: json)
225
- - `--api-key KEY` - API key (or set EXA_API_KEY env var)
226
-
227
- #### Advanced Search Options
228
-
229
- **Date Filtering:**
230
- ```bash
231
- # Filter by published date
232
- exa-ai search "AI research" \
233
- --start-published-date "2025-01-01T00:00:00.000Z" \
234
- --end-published-date "2025-12-31T23:59:59.999Z"
235
-
236
- # Filter by crawl date
237
- exa-ai search "news" \
238
- --start-crawl-date "2025-10-01T00:00:00.000Z" \
239
- --end-crawl-date "2025-10-31T23:59:59.999Z"
240
- ```
241
-
242
- **Text Filtering:**
243
- ```bash
244
- # Results must include specific phrase
245
- exa-ai search "machine learning" --include-text "neural networks"
246
-
247
- # Results must exclude specific phrase
248
- exa-ai search "programming" --exclude-text "paid-partnership"
249
-
250
- # Combine inclusion and exclusion
251
- exa-ai search "Python" \
252
- --include-text "open source" \
253
- --exclude-text "deprecated"
254
- ```
255
-
256
- **Content Extraction:**
257
- ```bash
258
- # Extract full webpage text
259
- exa-ai search "Ruby" --text
260
-
261
- # Extract text with options
262
- exa-ai search "AI" \
263
- --text \
264
- --text-max-characters 3000 \
265
- --include-html-tags
266
-
267
- # Generate AI summaries
268
- exa-ai search "climate change" \
269
- --summary \
270
- --summary-query "What are the main points?"
271
-
272
- # Format results as context for LLM RAG
273
- exa-ai search "kubernetes" \
274
- --context \
275
- --context-max-characters 5000
276
-
277
- # Crawl subpages
278
- exa-ai search "documentation" \
279
- --subpages 1 \
280
- --subpage-target about \
281
- --subpage-target docs
282
-
283
- # Extract links from results
284
- exa-ai search "web development" \
285
- --links 3 \
286
- --image-links 2
287
- ```
288
-
289
- **Advanced Ruby API:**
290
- ```ruby
291
- client = Exa::Client.new(api_key: "your-key")
292
-
293
- # Date range filtering
294
- results = client.search("AI research",
295
- start_published_date: "2025-01-01T00:00:00.000Z",
296
- end_published_date: "2025-12-31T23:59:59.999Z"
297
- )
298
-
299
- # Text filtering
300
- results = client.search("machine learning",
301
- include_text: ["neural networks"],
302
- exclude_text: ["cryptocurrency"]
303
- )
304
-
305
- # Full webpage text extraction
306
- results = client.search("Ruby",
307
- text: {
308
- max_characters: 3000,
309
- include_html_tags: true
310
- }
311
- )
312
-
313
- # AI-powered summaries
314
- results = client.search("climate change",
315
- summary: {
316
- query: "What are the main points?"
317
- }
318
- )
319
-
320
- # Context for RAG pipelines
321
- results = client.search("kubernetes",
322
- context: {
323
- max_characters: 5000
324
- }
325
- )
326
-
327
- # Subpage crawling
328
- results = client.search("documentation",
329
- subpages: 1,
330
- subpage_target: ["about", "docs", "guide"]
331
- )
332
-
333
- # Links and image extraction
334
- results = client.search("web development",
335
- extras: {
336
- links: 3,
337
- image_links: 2
338
- }
339
- )
340
-
341
- # Combine multiple features
342
- results = client.search("AI",
343
- num_results: 5,
344
- start_published_date: "2025-01-01T00:00:00.000Z",
345
- text: { max_characters: 3000 },
346
- summary: { query: "Main developments?" },
347
- context: { max_characters: 5000 },
348
- subpages: 1,
349
- subpage_target: ["research"],
350
- extras: { links: 3, image_links: 2 }
351
- )
352
-
353
- # Access extracted content
354
- results.results.each do |result|
355
- puts result["title"]
356
- puts result["text"] if result["text"] # Full webpage text
357
- puts result["summary"] if result["summary"] # AI summary
358
- puts result["links"] if result["links"] # Extracted links
359
- end
360
- ```
361
-
362
- ### Answer Command
363
-
364
- Generate comprehensive answers to questions using Exa's answer generation feature:
365
-
366
- ```bash
367
- # Basic question
368
- exa-ai answer "What is the capital of France?"
369
-
370
- # Get answer with source citations
371
- exa-ai answer "Latest developments in quantum computing"
372
-
373
- # Include full text from sources
374
- exa-ai answer "Ruby on Rails best practices" --text
375
-
376
- # Pretty formatted output
377
- exa-ai answer "How do I learn machine learning?" --output-format pretty
378
- ```
379
-
380
- **Options:**
381
- - `QUERY` - Question to answer (required)
382
- - `--text` - Include full text content from source pages
383
- - `--output-format FORMAT` - json or pretty (default: json)
384
- - `--api-key KEY` - API key (or set EXA_API_KEY env var)
385
-
386
- **Response fields:**
387
- - `answer` - The generated answer to your question
388
- - `citations` - Array of source citations with URLs
389
- - `cost_dollars` - Cost of the API request
390
-
391
- ### Context Command (Code Search)
392
-
393
- Find code snippets and context from open-source repositories:
394
-
395
- ```bash
396
- # Basic query
397
- exa-ai context "authentication with JWT"
398
-
399
- # With custom token allocation
400
- exa-ai context "React hooks" --tokens-num 5000
401
-
402
- # Text output
403
- exa-ai context "async/await patterns" --output-format text
404
- ```
405
-
406
- **Options:**
407
- - `QUERY` - Search query (required)
408
- - `--tokens-num NUM` - Token allocation, integer or "dynamic" (default: dynamic)
409
- - `--output-format FORMAT` - json or text (default: json)
410
- - `--api-key KEY` - API key
411
-
412
- ### Get-Contents Command
413
-
414
- Retrieve the full text content from web pages:
90
+ # Answer a question
91
+ exa-ai answer "What is machine learning?"
415
92
 
416
- ```bash
417
- # Single page
418
- exa-ai get-contents "https://example.com/article"
419
-
420
- # Multiple pages (comma-separated)
421
- exa-ai get-contents "https://site1.com,https://site2.com"
422
-
423
- # With options
424
- exa-ai get-contents "id1,id2,id3" \
425
- --text \
426
- --highlights \
427
- --output-format pretty
428
- ```
429
-
430
- **Options:**
431
- - `IDS` - Page IDs or URLs (required, comma-separated)
432
- - `--text` - Include full text content
433
- - `--highlights` - Include highlighted sections
434
- - `--summary` - Include summary
435
- - `--output-format FORMAT` - json or pretty (default: json)
436
- - `--api-key KEY` - API key
437
-
438
- ### Research Commands
439
-
440
- Start and manage long-running research tasks:
441
-
442
- #### research-start
443
-
444
- ```bash
445
- # Start a task
446
- exa-ai research-start --instructions "Find Ruby performance tips"
447
-
448
- # Start and wait for completion
449
- exa-ai research-start \
450
- --instructions "Analyze AI safety papers" \
451
- --model gpt-4 \
452
- --wait
453
-
454
- # With output schema
455
- exa-ai research-start \
456
- --instructions "Extract key metrics" \
457
- --output-schema '{"format":"json","fields":["metric","value"]}'
458
- ```
459
-
460
- **Options:**
461
- - `--instructions TEXT` - Research instructions (required)
462
- - `--model MODEL` - Model to use (e.g., gpt-4)
463
- - `--output-schema SCHEMA` - JSON schema for structured output
464
- - `--wait` - Wait for task to complete (with polling)
465
- - `--events` - Show event log during polling
466
- - `--output-format FORMAT` - json or pretty (default: json)
467
- - `--api-key KEY` - API key
468
-
469
- #### research-get
470
-
471
- ```bash
472
- # Check task status
473
- exa-ai research-get abc-123
474
-
475
- # With events
476
- exa-ai research-get abc-123 --events
477
-
478
- # Pretty output
479
- exa-ai research-get abc-123 --output-format pretty
480
- ```
481
-
482
- **Options:**
483
- - `RESEARCH_ID` - Task ID (required)
484
- - `--events` - Include event log
485
- - `--stream` - Stream results (premium feature)
486
- - `--output-format FORMAT` - json or pretty (default: json)
487
- - `--api-key KEY` - API key
488
-
489
- #### research-list
490
-
491
- ```bash
492
- # List all tasks
493
- exa-ai research-list
93
+ # Find code examples
94
+ exa-ai context "async/await error handling"
494
95
 
495
- # With pagination
496
- exa-ai research-list --limit 20
96
+ # Get page contents
97
+ exa-ai get-contents "https://example.com"
497
98
 
498
- # Next page
499
- exa-ai research-list --cursor "next_page_cursor"
500
-
501
- # Pretty table format
502
- exa-ai research-list --output-format pretty
99
+ # Start a research task
100
+ exa-ai research-start --instructions "Analyze recent ML papers" --wait
503
101
  ```
504
102
 
505
- **Options:**
506
- - `--cursor CURSOR` - Pagination cursor
507
- - `--limit N` - Results per page (default: 10)
508
- - `--output-format FORMAT` - json or pretty (default: json)
509
- - `--api-key KEY` - API key
510
-
511
- ### Global Options
103
+ ## Features
512
104
 
513
- All commands support:
514
- - `--api-key KEY` - Override API key
515
- - `--output-format FORMAT` - json, pretty, or text (varies by command)
516
- - `--help, -h` - Show command help
517
- - `exa-ai --version` - Show version
518
- - `exa-ai --help` - Show available commands
105
+ The gem provides complete access to Exa's API endpoints:
519
106
 
520
- ### Output Formats
521
-
522
- **JSON (default)**
523
- ```bash
524
- exa-ai search "ruby" --output-format json
525
- # Returns formatted JSON object
526
- ```
527
-
528
- **Pretty**
529
- ```bash
530
- exa-ai search "ruby" --output-format pretty
531
- # Returns human-readable format with titles, URLs, scores
532
- ```
533
-
534
- **Text**
535
- ```bash
536
- exa-ai context "React" --output-format text
537
- # Returns plain text output
538
- ```
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
539
112
 
540
113
  ## Error Handling
541
114
 
542
- The CLI provides helpful error messages:
543
-
544
- ```bash
545
- # Missing API key
546
- $ exa search "test"
547
- ❌ Configuration Error
548
-
549
- Missing API key. Set EXA_API_KEY or use --api-key
550
-
551
- Solutions:
552
- 1. Set the EXA_API_KEY environment variable:
553
- export EXA_API_KEY='your-api-key'
554
- ...
555
-
556
- # Invalid credentials
557
- $ exa search "test" --api-key bad-key
558
- ❌ Authentication Error
559
-
560
- Your API key is invalid or has expired.
561
- ...
562
-
563
- # Rate limited
564
- $ exa search "test" # After many requests
565
- ❌ Request Error
566
-
567
- You've exceeded the rate limit. Please wait before trying again.
568
- ```
569
-
570
- ### Ruby API Error Handling
571
-
572
115
  ```ruby
573
- client = Exa::Client.new(api_key: "test")
116
+ require 'exa-ai'
117
+
118
+ client = Exa::Client.new(api_key: "your-key")
574
119
 
575
120
  begin
576
121
  results = client.search("test")
577
122
  rescue Exa::Unauthorized => e
578
123
  puts "Invalid API key: #{e.message}"
579
124
  rescue Exa::TooManyRequests => e
580
- puts "Rate limited, please wait"
125
+ puts "Rate limited, please retry"
581
126
  rescue Exa::ServerError => e
582
- puts "API error: #{e.message}"
127
+ puts "Server error: #{e.message}"
583
128
  end
584
129
  ```
585
130
 
586
- ## Examples
587
-
588
- ### CLI Examples
589
-
590
- ```bash
591
- # Find Ruby tutorials
592
- exa search "Ruby best practices" --num-results 5
593
-
594
- # Get an answer to a question
595
- exa answer "What is machine learning?"
596
-
597
- # Get code examples for async/await
598
- exa context "async/await error handling"
599
-
600
- # Research AI trends
601
- exa research-start --instructions "What are latest AI trends?" --wait
602
-
603
- # Retrieve and analyze multiple pages
604
- exa get-contents "url1,url2,url3" --text --output-format pretty
605
- ```
606
-
607
- ### Ruby API Examples
608
-
609
- ```ruby
610
- require 'exa'
611
-
612
- Exa.configure do |config|
613
- config.api_key = ENV['EXA_API_KEY']
614
- end
615
-
616
- client = Exa::Client.new
617
-
618
- # Search with filtering
619
- results = client.search("kubernetes tutorial",
620
- num_results: 20,
621
- type: "neural",
622
- include_domains: ["kubernetes.io", "github.com"],
623
- use_autoprompt: true
624
- )
625
-
626
- results.results.each do |item|
627
- puts "#{item['title']} (#{item['url']})"
628
- end
131
+ ## Documentation
629
132
 
630
- # Get code context
631
- code_result = client.context("Docker best practices", tokens_num: 5000)
632
- puts code_result.response
633
-
634
- # Start async research
635
- task = client.research_start(
636
- instructions: "Summarize recent ML papers",
637
- model: "gpt-4"
638
- )
639
- puts "Task started: #{task.research_id}"
640
-
641
- # Poll for results
642
- loop do
643
- status = client.research_get(task.research_id)
644
- break if status.completed? || status.failed?
645
- sleep 5
646
- end
647
-
648
- if status.completed?
649
- puts status.output
650
- end
651
- ```
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
652
136
 
653
137
  ## Development
654
138
 
655
- ### Running Tests
656
-
657
- ```bash
658
- # Run all tests
659
- bundle exec rake test
660
-
661
- # Run specific test file
662
- bundle exec ruby test/cli/search_test.rb
663
-
664
- # Run with verbose output
665
- bundle exec rake test TESTOPTS="-v"
666
- ```
667
-
668
- ### Building the Gem
669
-
670
- ```bash
671
- bundle exec rake build
672
- bundle exec rake install
673
- ```
674
-
675
- ## Documentation
676
-
677
- - [Exa API Documentation](https://docs.exa.ai)
678
- - [API Reference](https://docs.exa.ai/reference)
679
- - [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
680
144
 
681
145
  ## Support
682
146
 
683
147
  - **Documentation**: https://docs.exa.ai
684
- - **API Key**: https://dashboard.exa.ai
148
+ - **Dashboard**: https://dashboard.exa.ai
685
149
  - **Status**: https://status.exa.ai
686
150
 
687
151
  ## License
688
152
 
689
- MIT License - See LICENSE file for details
690
-
691
- ## Changelog
692
-
693
- See [CHANGELOG.md](CHANGELOG.md) for version history and updates.
153
+ MIT License - See [LICENSE](LICENSE) file for details
694
154
 
695
155
  ---
696
156
 
697
- **Built with Exa.ai** - Search and discovery API for the web
157
+ **Built with [Exa.ai](https://exa.ai)** The search and discovery API