Module: RubynCode::LLM::ImageReader

Defined in:
lib/rubyn_code/llm/image_reader.rb

Overview

Reads image files from disk and returns image content blocks suitable for sending to the LLM as part of a user turn. Supports common raster formats accepted by both Anthropic and OpenAI vision APIs.

Constant Summary collapse

MAX_BYTES =
8 * 1024 * 1024
MEDIA_TYPES =
{
  '.png' => 'image/png',
  '.jpg' => 'image/jpeg',
  '.jpeg' => 'image/jpeg',
  '.gif' => 'image/gif',
  '.webp' => 'image/webp'
}.freeze
EXTENSIONS_REGEX =
/\.(png|jpe?g|gif|webp)\z/i

Class Method Summary collapse

Class Method Details

.data_uri(path) ⇒ Object

Build a base64 data URI of the form:

"data:image/png;base64,iVBORw0KG..."

Returns nil for non-image paths or unreadable/oversized files.



33
34
35
36
37
38
# File 'lib/rubyn_code/llm/image_reader.rb', line 33

def data_uri(path)
  block = for_path(path)
  return nil unless block

  "data:#{block.media_type};base64,#{block.data}"
end

.for_path(path) ⇒ LLM::ImageBlock?

Returns nil for non-image / unreadable paths.

Returns:



41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/rubyn_code/llm/image_reader.rb', line 41

def for_path(path)
  ext = File.extname(path)
  media = MEDIA_TYPES[ext.downcase] || MEDIA_TYPES[".#{ext.sub(/^\./, '').downcase}"]
  return nil unless media
  return nil unless File.file?(path)

  bytes = File.binread(path)
  return nil if bytes.bytesize > MAX_BYTES

  ImageBlock.new(media_type: media, data: Base64.strict_encode64(bytes))
rescue Errno::ENOENT, Errno::EACCES, ArgumentError
  nil
end

.image_extension?(path) ⇒ Boolean

Returns:

  • (Boolean)


55
56
57
# File 'lib/rubyn_code/llm/image_reader.rb', line 55

def image_extension?(path)
  path.to_s.match?(EXTENSIONS_REGEX)
end