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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae8ad5762410325124acdcada89aed1a88b18dcbecc8b85431b99b0c05e0f354
4
- data.tar.gz: b1d8ec27baf9bdf324af7183a6088e22e2437ef5d0bb0c97edee47eadeeed7de
3
+ metadata.gz: 6a7200f1be7297291b6fa6ecddfb0e87d49a9ef570a6bb73c00b7993a459daea
4
+ data.tar.gz: ac3a183a8ac848007659ab36cc759780e9724c9f2fdc5159b149eaf0633402af
5
5
  SHA512:
6
- metadata.gz: 1803b1811bc368be4d83bd9b02aa095c4f77f0dd97e05f3bd96ab9bc380d54b9a9bb7e17f5e3fca78c7a2f7348000f61bc55ec4875273eafa6dd0762fb09f7aa
7
- data.tar.gz: 0ec026a9d5b4d05c8779aa3e10df8c25c48e5a728f92608941e28f2b18a46238908af53837dfa234b22f2ad595922f03d1ce25f98f6b9f932ecce8570914a8aa
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 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,626 +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
- - `--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
- ```bash
416
- # Single page
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
- # With pagination
495
- exa-ai research-list --limit 20
96
+ # Get page contents
97
+ exa-ai get-contents "https://example.com"
496
98
 
497
- # Next page
498
- exa-ai research-list --cursor "next_page_cursor"
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
- **Options:**
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
- All commands support:
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
- ### Output Formats
520
-
521
- **JSON (default)**
522
- ```bash
523
- exa-ai search "ruby" --output-format json
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
- client = Exa::Client.new(api_key: "test")
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 wait"
125
+ puts "Rate limited, please retry"
580
126
  rescue Exa::ServerError => e
581
- puts "API error: #{e.message}"
127
+ puts "Server error: #{e.message}"
582
128
  end
583
129
  ```
584
130
 
585
- ## Examples
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
- # Get code context
629
- code_result = client.context("Docker best practices", tokens_num: 5000)
630
- puts code_result.response
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
- ### Running Tests
654
-
655
- ```bash
656
- # Run all tests
657
- bundle exec rake test
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
- - **API Key**: https://dashboard.exa.ai
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** - Search and discovery API for the web
157
+ **Built with [Exa.ai](https://exa.ai)** The search and discovery API
data/exe/exa-ai CHANGED
@@ -1,9 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "bundler/setup"
5
- require "exa"
6
- require "exa/cli/base"
4
+ require "exa-ai"
7
5
 
8
6
  # Global CLI interface for Exa API
9
7
 
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
- # Set up load paths
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
@@ -1,10 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "bundler/setup"
5
- require "exa"
6
- require "exa/cli/base"
7
- require "exa/cli/formatters/context_formatter"
4
+ require "exa-ai"
8
5
 
9
6
  # Parse command line arguments
10
7
  def parse_args(args)
@@ -1,10 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "bundler/setup"
5
- require "exa"
6
- require "exa/cli/base"
7
- require "exa/cli/formatters/contents_formatter"
4
+ require "exa-ai"
8
5
 
9
6
  # Parse command line arguments
10
7
  def parse_args(args)
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "bundler/setup"
5
- require "exa"
4
+ require "exa-ai"
6
5
 
7
6
  # Parse command-line arguments
8
7
  api_key = nil
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "bundler/setup"
5
- require "exa"
4
+ require "exa-ai"
6
5
 
7
6
  # Parse command-line arguments
8
7
  api_key = nil
@@ -1,9 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- # Set up load paths
5
- require "bundler/setup"
6
- require "exa"
4
+ require "exa-ai"
7
5
 
8
6
  # Parse command-line arguments
9
7
  def parse_args(argv)
data/exe/exa-ai-search CHANGED
@@ -1,9 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- # Set up load paths
5
- require "bundler/setup"
6
- require "exa"
4
+ require "exa-ai"
7
5
 
8
6
  # Parse command-line arguments
9
7
  def parse_args(argv)
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
@@ -161,6 +161,7 @@ module Exa
161
161
  options = {}
162
162
  options[:base_url] = @options[:base_url] if @options[:base_url]
163
163
  options[:timeout] = @options[:timeout] if @options[:timeout]
164
+ options[:debug] = true if ENV["EXA_DEBUG"]
164
165
  options
165
166
  end
166
167
 
@@ -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.request :authorization, "Bearer", api_key
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Exa
4
- VERSION = "0.3.0"
4
+ VERSION = "0.3.1"
5
5
  end
data/lib/exa-ai.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Main entry point for the exa-ai gem
4
+ # This file exists to avoid conflicts with the unrelated "exa" gem
5
+ require_relative "exa"
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.0
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