ruby-gemini-api 0.1.4 → 0.1.5

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: c80fbf2cb7142ab3ff7d6a17d8b5f1e43960ec8ed398ee7f4c35286ed72ce962
4
- data.tar.gz: 261f1a1e04757b93aac9c8a42263e355758bba4ec512f6c9dd408b63146e17fe
3
+ metadata.gz: e140bb695362a7924c1b633fbe0a5ac0a2dda14880a755157592024f3f4e719e
4
+ data.tar.gz: 5b6e2ec5d5be300ba558199c8ff2160e598615cbdb4e744209416fa7322bf0f6
5
5
  SHA512:
6
- metadata.gz: 780a9684677d9bfdd8945727c9cd00e1e0ecc9e43a63a038da17a18aa8e524e43f601946bd1fbc00c9406e4a45b80d59fedfdfc85e190b973cedd9c2340a5be4
7
- data.tar.gz: 399dff8bc6f6693b6267412b2fee067269125ea9b16ffd105d94b4ac9154ca1ade4246b6d3ca9aa9e7cb689e3f2d4a12ea771d4fc688de24e36688205675ab0f
6
+ metadata.gz: a2f3b01548fc4da69d1d1e77943444a164dc781940eeb1e7b8ee1d34eeca34db7f46e532f5b504175000145e11e0d343319da59111b87f2f403a99c08e6517e1
7
+ data.tar.gz: a84dcc5431abb1a4aa9753cec5a8e36106aa365cacf88b3d29998622382069f01650f11396a6867ce0b940e5faa4788fcb2eb7c744a27203a034f2918e353416
data/CHANGELOG.md CHANGED
@@ -13,4 +13,8 @@
13
13
  - Add support for multi-image input
14
14
 
15
15
  ## [0.1.4] - 2025-11-08
16
- - Add support for grounding search
16
+ - Add support for grounding search
17
+
18
+ ## [0.1.5] - 2025-11-13
19
+ - Add support for URL Context tool
20
+ - Add simplified method for accessing grounding search sources
data/README.md CHANGED
@@ -292,15 +292,13 @@ response = client.generate_content(
292
292
 
293
293
  if response.success?
294
294
  puts response.text
295
-
295
+
296
296
  # Check grounding information
297
297
  if response.grounded?
298
298
  puts "\nSource references:"
299
- response.grounding_chunks.each do |chunk|
300
- if chunk['web']
301
- puts "- #{chunk['web']['title']}"
302
- puts " #{chunk['web']['uri']}"
303
- end
299
+ response.grounding_sources.each do |source|
300
+ puts "- #{source[:title]}"
301
+ puts " #{source[:url]}"
304
302
  end
305
303
  end
306
304
  end
@@ -311,13 +309,15 @@ end
311
309
  ```ruby
312
310
  # Check if response is grounded
313
311
  if response.grounded?
314
- # Get full grounding metadata
312
+ # Get formatted source information (recommended)
313
+ response.grounding_sources.each do |source|
314
+ puts "Title: #{source[:title]}"
315
+ puts "URL: #{source[:url]}"
316
+ end
317
+
318
+ # You can also access raw metadata
315
319
  metadata = response.grounding_metadata
316
-
317
- # Get source chunks (references)
318
320
  chunks = response.grounding_chunks
319
-
320
- # Get search entry point
321
321
  entry_point = response.search_entry_point
322
322
  end
323
323
  ```
@@ -345,6 +345,86 @@ You can find a grounding search demo in:
345
345
  ruby demo/grounding_search_demo_ja.rb
346
346
  ```
347
347
 
348
+ ### URL Context
349
+
350
+ You can use Gemini API's URL Context feature to retrieve and analyze content from web pages.
351
+
352
+ #### Basic Usage
353
+
354
+ ```ruby
355
+ require 'gemini'
356
+
357
+ client = Gemini::Client.new(ENV['GEMINI_API_KEY'])
358
+
359
+ # Use URL Context to analyze web pages (shortcut)
360
+ response = client.generate_content(
361
+ "Summarize the content of this page: https://www.ruby-lang.org",
362
+ model: "gemini-2.5-flash",
363
+ url_context: true
364
+ )
365
+
366
+ if response.success?
367
+ puts response.text
368
+ end
369
+ ```
370
+
371
+ #### Using Explicit Tools Parameter
372
+
373
+ ```ruby
374
+ # Explicit tools parameter
375
+ response = client.generate_content(
376
+ "Compare these two pages: https://www.ruby-lang.org and https://www.python.org",
377
+ model: "gemini-2.5-flash",
378
+ tools: [{ url_context: {} }]
379
+ )
380
+ ```
381
+
382
+ #### Combining URL Context with Google Search
383
+
384
+ ```ruby
385
+ # Use both URL Context and Google Search
386
+ response = client.generate_content(
387
+ "What is the latest information about Ruby from https://www.ruby-lang.org and recent news?",
388
+ model: "gemini-2.5-flash",
389
+ url_context: true,
390
+ google_search: true
391
+ )
392
+ ```
393
+
394
+ #### Checking URL Context Metadata
395
+
396
+ ```ruby
397
+ # Check if URL Context was used
398
+ if response.url_context?
399
+ # Get full metadata
400
+ metadata = response.url_context_metadata
401
+
402
+ # Get retrieved URL information
403
+ urls = response.retrieved_urls
404
+
405
+ # Check retrieval status for each URL
406
+ response.url_retrieval_statuses.each do |url_info|
407
+ puts "URL: #{url_info[:url]}"
408
+ puts "Status: #{url_info[:status]}"
409
+ puts "Title: #{url_info[:title]}" if url_info[:title]
410
+ end
411
+ end
412
+ ```
413
+
414
+ #### Limitations
415
+
416
+ - Maximum 20 URLs per request
417
+ - Maximum 34MB content size per URL
418
+ - YouTube videos and paywalled content are not supported
419
+
420
+ #### Demo Application
421
+
422
+ You can find a URL context demo in:
423
+
424
+ ```bash
425
+ ruby demo/url_context_demo.rb https://www.ruby-lang.org
426
+ ```
427
+
348
428
  ### Image Generation
349
429
 
350
430
  ```ruby
data/lib/gemini/client.rb CHANGED
@@ -117,8 +117,9 @@ module Gemini
117
117
  # Helper methods for convenience
118
118
 
119
119
  # Method with usage similar to OpenAI's chat
120
- def generate_content(prompt, model: "gemini-2.0-flash-lite", system_instruction: nil,
121
- response_mime_type: nil, response_schema: nil, temperature: 0.5, tools: nil, **parameters, &stream_callback)
120
+ def generate_content(prompt, model: "gemini-2.0-flash-lite", system_instruction: nil,
121
+ response_mime_type: nil, response_schema: nil, temperature: 0.5, tools: nil,
122
+ url_context: false, google_search: false, **parameters, &stream_callback)
122
123
  content = format_content(prompt)
123
124
  params = {
124
125
  contents: [content],
@@ -137,7 +138,11 @@ module Gemini
137
138
  if response_schema
138
139
  params[:generation_config]["response_schema"] = response_schema
139
140
  end
140
- params[:tools] = tools if tools
141
+
142
+ # Handle tool shortcuts
143
+ tools = build_tools_array(tools, url_context: url_context, google_search: google_search)
144
+ params[:tools] = tools if tools && !tools.empty?
145
+
141
146
  params.merge!(parameters)
142
147
 
143
148
  if block_given?
@@ -149,32 +154,38 @@ module Gemini
149
154
 
150
155
  # Streaming text generation
151
156
  def generate_content_stream(prompt, model: "gemini-2.0-flash-lite", system_instruction: nil,
152
- response_mime_type: nil, response_schema: nil, temperature: 0.5, **parameters, &block)
157
+ response_mime_type: nil, response_schema: nil, temperature: 0.5,
158
+ url_context: false, google_search: false, **parameters, &block)
153
159
  raise ArgumentError, "Block is required for streaming" unless block_given?
154
-
160
+
155
161
  content = format_content(prompt)
156
162
  params = {
157
163
  contents: [content],
158
164
  model: model
159
165
  }
160
-
166
+
161
167
  if system_instruction
162
168
  params[:system_instruction] = format_content(system_instruction)
163
169
  end
164
-
170
+
165
171
  params[:generation_config] ||= {}
166
-
172
+
167
173
  if response_mime_type
168
174
  params[:generation_config][:response_mime_type] = response_mime_type
169
175
  end
170
-
176
+
171
177
  if response_schema
172
178
  params[:generation_config][:response_schema] = response_schema
173
179
  end
174
180
  params[:generation_config]["temperature"] = temperature
181
+
182
+ # Handle tool shortcuts
183
+ tools = build_tools_array(nil, url_context: url_context, google_search: google_search)
184
+ params[:tools] = tools if tools && !tools.empty?
185
+
175
186
  # Merge other parameters
176
187
  params.merge!(parameters)
177
-
188
+
178
189
  chat(parameters: params, &block)
179
190
  end
180
191
 
@@ -399,7 +410,29 @@ module Gemini
399
410
  end
400
411
 
401
412
  private
402
-
413
+
414
+ # Build tools array from explicit tools parameter and shortcuts
415
+ def build_tools_array(tools, url_context: false, google_search: false)
416
+ result_tools = []
417
+
418
+ # Add existing tools if provided
419
+ if tools.is_a?(Array)
420
+ result_tools.concat(tools)
421
+ elsif tools
422
+ result_tools << tools
423
+ end
424
+
425
+ # Add url_context tool if requested
426
+ result_tools << { url_context: {} } if url_context
427
+
428
+ # Add google_search tool if requested
429
+ result_tools << { google_search: {} } if google_search
430
+
431
+ # Remove duplicates based on tool keys and return
432
+ return nil if result_tools.empty?
433
+ result_tools.uniq { |tool| tool.keys.first }
434
+ end
435
+
403
436
  # Process stream chunk and pass to callback
404
437
  def process_stream_chunk(chunk, &callback)
405
438
  if chunk.respond_to?(:dig) && chunk.dig("candidates", 0, "content", "parts", 0, "text")
@@ -119,6 +119,57 @@ module Gemini
119
119
  def search_entry_point
120
120
  grounding_metadata&.dig("searchEntryPoint", "renderedContent")
121
121
  end
122
+
123
+ # Get formatted grounding sources (simplified access)
124
+ def grounding_sources
125
+ return [] unless grounded?
126
+
127
+ grounding_chunks.map do |chunk|
128
+ if chunk["web"]
129
+ {
130
+ url: chunk["web"]["uri"],
131
+ title: chunk["web"]["title"],
132
+ type: "web"
133
+ }
134
+ else
135
+ # Handle other potential chunk types
136
+ {
137
+ type: "unknown",
138
+ data: chunk
139
+ }
140
+ end
141
+ end
142
+ end
143
+
144
+ # Get URL context metadata (for URL Context tool)
145
+ def url_context_metadata
146
+ first_candidate&.dig("urlContextMetadata")
147
+ end
148
+
149
+ # Check if response has URL context metadata
150
+ def url_context?
151
+ !url_context_metadata.nil? && !url_context_metadata.empty?
152
+ end
153
+
154
+ # Get retrieved URLs from URL context
155
+ def retrieved_urls
156
+ return [] unless url_context?
157
+
158
+ url_context_metadata&.dig("urlMetadata") || []
159
+ end
160
+
161
+ # Get URL retrieval statuses
162
+ def url_retrieval_statuses
163
+ return [] unless url_context?
164
+
165
+ retrieved_urls.map do |url_info|
166
+ {
167
+ url: url_info["retrievedUrl"],
168
+ status: url_info["urlRetrievalStatus"],
169
+ title: url_info["title"]
170
+ }
171
+ end
172
+ end
122
173
 
123
174
 
124
175
  # Get token usage information
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Gemini
4
- VERSION = "0.1.4"
4
+ VERSION = "0.1.5"
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-gemini-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - rira100000000
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-11-07 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: faraday
@@ -172,7 +171,6 @@ metadata:
172
171
  source_code_uri: https://github.com/rira100000000/ruby-gemini-api
173
172
  changelog_uri: https://github.com/rira100000000/ruby-gemini-api/blob/main/CHANGELOG.md
174
173
  rubygems_mfa_required: 'true'
175
- post_install_message:
176
174
  rdoc_options: []
177
175
  require_paths:
178
176
  - lib
@@ -187,8 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
187
185
  - !ruby/object:Gem::Version
188
186
  version: '0'
189
187
  requirements: []
190
- rubygems_version: 3.5.11
191
- signing_key:
188
+ rubygems_version: 3.7.2
192
189
  specification_version: 4
193
190
  summary: Ruby client for Google's Gemini API
194
191
  test_files: []