mindee-lite 5.2.0 → 5.2.2

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: 426b1664ea37257f3e79f9da29fca7096392ba5c9fca021279acb79ae8c4c80b
4
- data.tar.gz: dfa07b33ef6c2da5f5d973fa47c01ff969bcd011e3b595785f2f06dd411b4c4c
3
+ metadata.gz: f309aa0cd9c594dd11e44b754a6f313f56786ddc0e03b7ea1503d38d48ae4701
4
+ data.tar.gz: c00cd97ccded0ac194a1311d45adc36baa04c5e932fd49248b46c59e065c71f7
5
5
  SHA512:
6
- metadata.gz: f7cd5d72568f93b852368f0e85244ca7453932f9f0fde1b0623a1fcc6cd9f53ff16a571f0ce1ca19c810ce51e2740718984c08150e6e03d9b18b4f0a4aa8c67a
7
- data.tar.gz: 10644668f5aa9b0c2848e252cfe8174368c3bd49f5483028c9d0a7e316356986c0300acd875e162156e5338ff53d3d297e47aec5fd33ca9824e39d3d3181272b
6
+ metadata.gz: bc4983fa4d22c23b4fac65c3d9d36441114c8a94117f4aed73dd628aca2ea1b1216ad05cc0cadd2b1f9298c98561f674786c559eb69b4f40184c1e8960a06fdd
7
+ data.tar.gz: d53c54dee59e8f1ee9ff6b62267def50a08248d27e491f2d5ccd53a28277812167c507efa7f1f990cb7a264985df126b7a9cb8c544c728dd98a5d243207b26f2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Mindee Ruby API Library Changelog
2
2
 
3
+ ## v5.2.2 - 2026-06-18
4
+ ### Changes
5
+ * :recycle: refactor CLI to conform with other client libraries
6
+ * :recycle: add secondary accessor for search model pagination to match json return
7
+ * :recycle: ensure HEIF images are detected as such and properly handled
8
+
9
+
10
+ ## v5.2.1 - 2026-05-27
11
+ ### Changes
12
+ * :recycle: add polling options as a dedicated parameter (#252)
13
+
14
+
3
15
  ## v5.2.0 - 2026-05-19
4
16
  ### Changes
5
17
  * :sparkles: add webhook info to model searches
data/bin/mindee.rb CHANGED
@@ -6,24 +6,29 @@ require 'optparse'
6
6
  require_relative 'v1/parser'
7
7
  require_relative 'v2/parser'
8
8
 
9
- def setup_main_parser
10
- v1_parser = MindeeCLI::V1Parser.new(ARGV)
11
- v2_parser = MindeeCLI::V2Parser.new(ARGV)
12
- main_parser = OptionParser.new do |opts|
13
- opts.banner = "Usage: mindee [command]"
14
- opts.separator "Commands:"
15
- opts.separator " v1 Use Version 1 of the Mindee API"
16
- opts.separator " v2 Use Version 2 of the Mindee API"
9
+ def root_help
10
+ help = "Usage: mindee command [options]\n\nAvailable commands:\n"
11
+ help += " #{'v1'.ljust(50)}Use Version 1 of the Mindee API\n"
12
+ help += " #{'search-models'.ljust(50)}Search for available models for this API key\n"
13
+
14
+ V2_PRODUCTS.each do |product_key, product_values|
15
+ help += " #{product_key.ljust(50)}#{product_values[:description]}\n"
17
16
  end
18
- main_command = ARGV.shift
19
17
 
20
- case main_command
21
- when 'v1'
22
- v1_parser.execute
23
- when 'v2'
24
- v2_parser.execute
18
+ help
19
+ end
20
+
21
+ def setup_main_parser
22
+ main_command = ARGV.first
23
+
24
+ if main_command == 'v1'
25
+ ARGV.shift
26
+ MindeeCLI::V1Parser.new(ARGV).execute
27
+ elsif main_command.nil? || %w[help -h --help].include?(main_command)
28
+ abort(root_help)
25
29
  else
26
- abort(main_parser.help)
30
+ ARGV.shift if main_command == 'v2'
31
+ MindeeCLI::V2Parser.new(ARGV, command_prefix: 'mindee').execute
27
32
  end
28
33
  end
29
34
 
data/bin/v2/parser.rb CHANGED
@@ -19,10 +19,11 @@ module MindeeCLI
19
19
  # @return [Parser]
20
20
  attr_reader :search_parser
21
21
 
22
- def initialize(arguments)
22
+ def initialize(arguments, command_prefix: 'mindee v2')
23
23
  @arguments = arguments
24
+ @command_prefix = command_prefix
24
25
  @options_parser = OptionParser.new do |opts|
25
- opts.banner = 'Usage: mindee v2 command [options]'
26
+ opts.banner = "Usage: #{@command_prefix} command [options]"
26
27
  end
27
28
  @product_parser = init_product_parser
28
29
  @search_parser = init_search_parser
@@ -67,6 +68,8 @@ module MindeeCLI
67
68
  else
68
69
  abort("#{e.message}\n\n#{@product_parser[command].help}")
69
70
  end
71
+ rescue Mindee::Error::MindeeError => e
72
+ abort(format_cli_error(e))
70
73
  end
71
74
 
72
75
  private
@@ -83,9 +86,21 @@ module MindeeCLI
83
86
  abort(error_msg)
84
87
  end
85
88
 
89
+ def format_cli_error(error)
90
+ if error.is_a?(Mindee::Error::MindeeHTTPErrorV2) && error.status.to_i == 401
91
+ "CLI error: Missing credentials. Provide an API key using '--key' or " \
92
+ "the 'MINDEE_V2_API_KEY' environment variable."
93
+ elsif error.is_a?(Mindee::Error::MindeeAPIError) && error.message.include?('Missing API key')
94
+ "CLI error: Missing API key. Provide it using '--key' or " \
95
+ "the 'MINDEE_V2_API_KEY' environment variable."
96
+ else
97
+ "CLI error: #{error.message}"
98
+ end
99
+ end
100
+
86
101
  def init_search_parser
87
102
  OptionParser.new do |options_parser|
88
- options_parser.banner = 'Usage: mindee v2 search-models [options]'
103
+ options_parser.banner = "Usage: #{@command_prefix} search-models [options]"
89
104
  init_common_options(options_parser)
90
105
  options_parser.on('-n [NAME]', '--name [NAME]',
91
106
  'Search for partial matches in model name. Note: case insensitive') do |v|
@@ -159,7 +174,7 @@ module MindeeCLI
159
174
  v2_product_parser = {}
160
175
  V2_PRODUCTS.each do |product_key, product_values|
161
176
  v2_product_parser[product_key] = OptionParser.new do |options_parser|
162
- options_parser.banner = "Usage: mindee v2 #{product_key} [options] file"
177
+ options_parser.banner = "Usage: #{@command_prefix} #{product_key} [options] file"
163
178
  options_parser.on('-m MODEL_ID', '--model-id MODEL_ID', 'Model ID') { |v| @options[:model_id] = v }
164
179
  options_parser.on('-a ALIAS', '--alias ALIAS', 'Add a file alias to the response') do |v|
165
180
  @options[:alias] = v
@@ -3,6 +3,7 @@
3
3
  module Mindee
4
4
  # Centralized check for optional heavy dependencies
5
5
  module Dependencies
6
+ # Checks the presence of dependencies.
6
7
  def self.check_all_dependencies
7
8
  require 'origami'
8
9
  require 'mini_magick'
@@ -12,16 +13,20 @@ module Mindee
12
13
  false
13
14
  end
14
15
 
16
+ # Memoized check.
15
17
  @all_deps_available = check_all_dependencies
16
18
 
19
+ # Checks whether all dependencies are available.
17
20
  def self.all_deps_available?
18
21
  check_all_dependencies
19
22
  end
20
23
 
24
+ # Raises an error if dependencies are not available.
21
25
  def self.require_all_deps!
22
26
  raise LoadError, MINDEE_DEPENDENCIES_LOAD_ERROR unless all_deps_available?
23
27
  end
24
28
 
29
+ # Error message to display when dependencies are not available.
25
30
  MINDEE_DEPENDENCIES_LOAD_ERROR = 'Attempted to load Mindee PDF/Image tools without required dependencies. ' \
26
31
  "If you need to process local files, please replace the 'mindee-lite' gem " \
27
32
  "with the standard 'mindee' gem in your Gemfile."
@@ -9,7 +9,7 @@ module Mindee
9
9
  # @param image [MiniMagick::Image, StringIO] Input image.
10
10
  # @param quality [Integer, nil] Quality of the final file.
11
11
  # @param max_width [Integer, nil] Maximum width. If not specified, the horizontal ratio will remain the same.
12
- # @param max_height [Integer] Maximum height. If not specified, the vertical ratio will remain the same.
12
+ # @param max_height [Integer, nil] Maximum height. If not specified, the vertical ratio will remain the same.
13
13
  # @return [StringIO]
14
14
  def self.compress_image(image, quality: 85, max_width: nil, max_height: nil)
15
15
  processed_image = ImageUtils.to_image(image)
@@ -22,7 +22,7 @@ module Mindee
22
22
  # @param [String] model_id ID of the model
23
23
  # @param [String, nil] file_alias File alias, if applicable.
24
24
  # @param [Array<String>, nil] webhook_ids List of webhook IDs to propagate the API response to.
25
- # @param [Hash, nil] polling_options Options for polling. Set only if having timeout issues.
25
+ # @param [Hash, PollingOptions, nil] polling_options Options for polling. Set only if having timeout issues.
26
26
  # @param [Boolean, nil] close_file Whether to close the file after parsing.
27
27
  def initialize(
28
28
  model_id,
@@ -40,6 +40,13 @@ module Mindee
40
40
  @close_file = close_file.nil? || close_file
41
41
  end
42
42
 
43
+ # Sets polling options after normalizing hash inputs.
44
+ # @param [Hash, PollingOptions, nil] polling_options
45
+ # @return [PollingOptions]
46
+ def polling_options=(polling_options)
47
+ @polling_options = get_clean_polling_options(polling_options)
48
+ end
49
+
43
50
  # @return [String] Slug for the endpoint.
44
51
  def self.slug
45
52
  if self == BaseParameters
@@ -16,6 +16,7 @@ module Mindee
16
16
  ALLOWED_MIME_TYPES = [
17
17
  'application/pdf',
18
18
  'image/heic',
19
+ 'image/heif',
19
20
  'image/png',
20
21
  'image/jpeg',
21
22
  'image/tiff',
@@ -37,11 +38,7 @@ module Mindee
37
38
  def initialize(io_stream, filename, repair_pdf: false)
38
39
  @io_stream = io_stream
39
40
  @filename = filename
40
- @file_mimetype = if repair_pdf
41
- Marcel::MimeType.for @io_stream
42
- else
43
- Marcel::MimeType.for @io_stream, name: @filename
44
- end
41
+ @file_mimetype = detect_mime_type(repair_pdf)
45
42
  if ALLOWED_MIME_TYPES.include? @file_mimetype
46
43
  logger.debug("Loaded new input #{@filename} from #{self.class}")
47
44
  return
@@ -83,12 +80,14 @@ module Mindee
83
80
  # @return [StringIO] The fixed stream.
84
81
  # @raise [Mindee::Error::MindeePDFError]
85
82
  def self.fix_pdf(stream, maximum_offset: 500)
86
- out_stream = StringIO.new
83
+ out_stream = StringIO.new(''.b)
87
84
  stream.gets('%PDF-')
88
85
  raise Error::MindeePDFError if stream.eof? || stream.pos > maximum_offset
89
86
 
90
87
  stream.pos = stream.pos - 5
91
- out_stream << stream.read
88
+ out_stream.write(stream.read.to_s.b)
89
+ out_stream.rewind
90
+ out_stream
92
91
  end
93
92
 
94
93
  # Cuts a PDF file according to provided options.
@@ -195,6 +194,28 @@ module Mindee
195
194
 
196
195
  Mindee::PDF::PDFTools.source_text?(@io_stream)
197
196
  end
197
+
198
+ private
199
+
200
+ # Checks the mimetype for the file. If it is a PDF, it will attempt to repair it if repair_pdf is true.
201
+ # @param repair_pdf [bool] Whether to attempt to repair the PDF.
202
+ # @return [String] The mimetype of the file.
203
+ def detect_mime_type(repair_pdf)
204
+ return Marcel::MimeType.for(@io_stream) if repair_pdf
205
+
206
+ heif_mimetype_from_extension || Marcel::MimeType.for(@io_stream, name: @filename)
207
+ end
208
+
209
+ # Checks the file extension for a HEIF mimetype.
210
+ # @return [String, nil] The mimetype if found, nil otherwise.
211
+ def heif_mimetype_from_extension
212
+ case File.extname(@filename.to_s).downcase
213
+ when '.heic'
214
+ 'image/heic'
215
+ when '.heif'
216
+ 'image/heif'
217
+ end
218
+ end
198
219
  end
199
220
 
200
221
  # Replaces non-ASCII characters by their UNICODE escape sequence.
@@ -57,14 +57,16 @@ module Mindee
57
57
  # @param input_source [Mindee::Input::Source::LocalInputSource, Mindee::Input::Source::URLInputSource]
58
58
  # The source of the input document (local file or URL).
59
59
  # @param params [Hash, Input::BaseParameters] Parameters for the inference.
60
+ # @param polling_options [Hash, PollingOptions, nil] Parameters for polling.
60
61
  # @return [Parsing::BaseResponse]
61
62
  def enqueue_and_get_result(
62
63
  product,
63
64
  input_source,
64
- params
65
+ params,
66
+ polling_options = nil
65
67
  )
66
68
  enqueue_response = enqueue(product, input_source, params)
67
- normalized_params = normalize_parameters(product.params_type, params)
69
+ normalized_params = normalize_parameters(product.params_type, params, polling_options: polling_options)
68
70
  normalized_params.validate_async_params
69
71
 
70
72
  if enqueue_response.job.id.nil? || enqueue_response.job.id.empty?
@@ -121,8 +123,14 @@ module Mindee
121
123
 
122
124
  # If needed, converts the parsing options provided as a hash into a proper BaseParameters subclass object.
123
125
  # @param params [Hash, Class<BaseParameters>] Params.
126
+ # @param polling_options [Hash, PollingOptions, nil] Polling options.
124
127
  # @return [BaseParameters]
125
- def normalize_parameters(param_class, params)
128
+ def normalize_parameters(param_class, params, polling_options: nil)
129
+ if params.is_a?(Hash)
130
+ params[:polling_options] = polling_options if polling_options
131
+ elsif params.is_a?(Mindee::Input::BaseParameters) && !polling_options.nil?
132
+ params.polling_options = polling_options
133
+ end
126
134
  return param_class.from_hash(params: params) if params.is_a?(Hash)
127
135
 
128
136
  params
@@ -6,16 +6,19 @@ module Mindee
6
6
  module Search
7
7
  # Models search response.
8
8
  class SearchResponse < CommonResponse
9
- # @return [Search::Search] Parsed search payload.
9
+ # @return [Search::SearchModels] Parsed search payload.
10
10
  attr_reader :models
11
- # @return [Search::Search] Pagination metadata.
11
+ # @return [Search::PaginationMetadata] Pagination metadata.
12
+ attr_reader :pagination
13
+ # @return [Search::PaginationMetadata] Pagination metadata.
12
14
  attr_reader :pagination_metadata
13
15
 
14
16
  def initialize(server_response)
15
17
  super
16
18
 
17
- @models = Search::SearchModels.new(server_response['models'])
18
- @pagination_metadata = PaginationMetadata.new(server_response['pagination'])
19
+ @models = SearchModels.new(server_response['models'])
20
+ @pagination = PaginationMetadata.new(server_response['pagination'])
21
+ @pagination_metadata = @pagination
19
22
  end
20
23
 
21
24
  # String representation.
@@ -27,7 +30,7 @@ module Mindee
27
30
  @models.to_s,
28
31
  'Pagination Metadata',
29
32
  '###################',
30
- @pagination_metadata.to_s,
33
+ @pagination.to_s,
31
34
  '',
32
35
  ].join("\n")
33
36
  end
@@ -16,7 +16,7 @@ module Mindee
16
16
  # @param [String] model_id ID of the model
17
17
  # @param [String, nil] file_alias File alias, if applicable.
18
18
  # @param [Array<String>, nil] webhook_ids List of webhook IDs to propagate the API response to.
19
- # @param [Hash, nil] polling_options Options for polling. Set only if having timeout issues.
19
+ # @param [Hash, PollingOptions, nil] polling_options Options for polling. Set only if having timeout issues.
20
20
  # @param [Boolean, nil] close_file Whether to close the file after parsing.
21
21
  def initialize(
22
22
  model_id,
@@ -16,7 +16,7 @@ module Mindee
16
16
  # @param [String] model_id ID of the model
17
17
  # @param [String, nil] file_alias File alias, if applicable.
18
18
  # @param [Array<String>, nil] webhook_ids List of webhook IDs to propagate the API response to.
19
- # @param [Hash, nil] polling_options Options for polling. Set only if having timeout issues.
19
+ # @param [Hash, PollingOptions, nil] polling_options Options for polling. Set only if having timeout issues.
20
20
  # @param [Boolean, nil] close_file Whether to close the file after parsing.
21
21
  def initialize(
22
22
  model_id,
@@ -13,7 +13,7 @@ module Mindee
13
13
  # @return [Mindee::V2::Product::Extraction::Params::DataSchemaReplace]
14
14
  attr_reader :replace
15
15
 
16
- # @param data_schema [Hash, String]
16
+ # @param data_schema [Hash, DataSchema, String]
17
17
  def initialize(data_schema)
18
18
  case data_schema
19
19
  when String
@@ -46,7 +46,7 @@ module Mindee
46
46
  # @param [String, nil] file_alias File alias, if applicable.
47
47
  # @param [Array<String>, nil] webhook_ids
48
48
  # @param [String, nil] text_context
49
- # @param [Hash, nil] polling_options
49
+ # @param [Hash, PollingOptions, nil] polling_options
50
50
  # @param [Boolean, nil] close_file
51
51
  # @param [DataSchemaField, String, Hash nil] data_schema
52
52
  def initialize(
@@ -16,7 +16,7 @@ module Mindee
16
16
  # @param [String] model_id ID of the model
17
17
  # @param [String, nil] file_alias File alias, if applicable.
18
18
  # @param [Array<String>, nil] webhook_ids List of webhook IDs to propagate the API response to.
19
- # @param [Hash, nil] polling_options Options for polling. Set only if having timeout issues.
19
+ # @param [Hash, PollingOptions, nil] polling_options Options for polling. Set only if having timeout issues.
20
20
  # @param [Boolean, nil] close_file Whether to close the file after parsing.
21
21
  def initialize(
22
22
  model_id,
@@ -17,7 +17,7 @@ module Mindee
17
17
  # @param [String] model_id ID of the model
18
18
  # @param [String, nil] file_alias File alias, if applicable.
19
19
  # @param [Array<String>, nil] webhook_ids List of webhook IDs to propagate the API response to.
20
- # @param [Hash, nil] polling_options Options for polling. Set only if having timeout issues.
20
+ # @param [Hash, PollingOptions, nil] polling_options Options for polling. Set only if having timeout issues.
21
21
  # @param [Boolean, nil] close_file Whether to close the file after parsing.
22
22
  def initialize(
23
23
  model_id,
@@ -3,7 +3,7 @@
3
3
  # Mindee
4
4
  module Mindee
5
5
  # Current version.
6
- VERSION = '5.2.0'
6
+ VERSION = '5.2.2'
7
7
 
8
8
  # Finds and return the current platform.
9
9
  # @return [Symbol, Hash[String | Symbol, Regexp], Nil?]
@@ -26,6 +26,7 @@ module Mindee
26
26
 
27
27
  def append_form_data: (Array[Array[untyped]]) -> Array[Array[untyped]]
28
28
  def validate_async_params: () -> void
29
+ def polling_options=: (Hash[Symbol | String, untyped] | PollingOptions?) -> PollingOptions
29
30
 
30
31
  private
31
32
 
@@ -23,6 +23,12 @@ module Mindee
23
23
  def write_to_file: (String?) -> void
24
24
  def compress!: (?quality: Integer, ?max_width: Integer?, ?max_height: Integer?, ?force_source_text: bool, ?disable_source_text: bool) -> Integer
25
25
  def source_text?: -> bool?
26
+
27
+ private
28
+
29
+ def detect_mime_type: (bool) -> String
30
+
31
+ def heif_mimetype_from_extension: -> String?
26
32
  end
27
33
  def self.convert_to_unicode_escape: (String) -> String
28
34
  end
@@ -17,13 +17,13 @@ module Mindee
17
17
 
18
18
  def enqueue: [T] (HTTP::_ProductClass[T] product, Input::Source::LocalInputSource | Input::Source::URLInputSource, Hash[String | Symbol, untyped] | Input::BaseParameters params) -> V2::Parsing::JobResponse
19
19
 
20
- def enqueue_and_get_result: [T] (HTTP::_ProductClass[T] product, Input::Source::LocalInputSource | Input::Source::URLInputSource, Hash[String | Symbol, untyped] | Input::BaseParameters params) -> T
20
+ def enqueue_and_get_result: [T] (HTTP::_ProductClass[T] product, Input::Source::LocalInputSource | Input::Source::URLInputSource, Hash[String | Symbol, untyped] | Input::BaseParameters params, ?Hash[String | Symbol, untyped] | Input::PollingOptions?) -> T
21
21
 
22
22
  def search_models: (String?, String?) -> Mindee::V2::Parsing::Search::SearchResponse
23
23
 
24
24
  def validate_async_params: (Integer | Float, Integer | Float, Integer) -> void
25
25
 
26
- def normalize_parameters: (singleton(Input::BaseParameters) param_class, Hash[String | Symbol, untyped] | Input::BaseParameters params) -> Input::BaseParameters
26
+ def normalize_parameters: (singleton(Input::BaseParameters) param_class, Hash[String | Symbol, untyped] | Input::BaseParameters params, ?polling_options: Hash[String | Symbol, untyped] | Input::PollingOptions?) -> Input::BaseParameters
27
27
  end
28
28
  end
29
29
  end
@@ -0,0 +1,13 @@
1
+ # lib/mindee/v2/parsing/search/search_models.rb
2
+
3
+ module Mindee
4
+ module V2
5
+ module Parsing
6
+ module Search
7
+ # Array of search models.
8
+ class SearchModels < Array[SearchModel]
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -5,6 +5,7 @@ module Mindee
5
5
  module Search
6
6
  class SearchResponse
7
7
  attr_reader models: Array[SearchResponse]
8
+ attr_reader pagination: PaginationMetadata
8
9
  attr_reader pagination_metadata: PaginationMetadata
9
10
 
10
11
  def initialize: (Hash[String|Symbol, untyped]) -> void
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mindee-lite
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.0
4
+ version: 5.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mindee, SA
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-05-19 00:00:00.000000000 Z
11
+ date: 2026-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -57,8 +57,8 @@ description: Quickly and easily connect to Mindee's API services using Ruby. Thi
57
57
  email:
58
58
  - opensource@mindee.co
59
59
  executables:
60
- - mindee.rb
61
60
  - console
61
+ - mindee.rb
62
62
  extensions: []
63
63
  extra_rdoc_files: []
64
64
  files:
@@ -535,6 +535,7 @@ files:
535
535
  - sig/mindee/v2/parsing/search/model_webhook.rbs
536
536
  - sig/mindee/v2/parsing/search/pagination_metadata.rbs
537
537
  - sig/mindee/v2/parsing/search/search_model.rbs
538
+ - sig/mindee/v2/parsing/search/search_models.rbs
538
539
  - sig/mindee/v2/parsing/search/search_response.rbs
539
540
  - sig/mindee/v2/parsing/search_models.rbs
540
541
  - sig/mindee/v2/product/base_product.rbs