mindee-lite 5.3.1 → 5.5.0

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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.git-hooks/pre_commit/gitleaks.rb +19 -0
  3. data/.overcommit.yml +46 -0
  4. data/CHANGELOG.md +14 -0
  5. data/CONTRIBUTING.md +128 -0
  6. data/bin/mindee.rb +4 -1
  7. data/bin/v2/parser.rb +40 -45
  8. data/bin/v2/search_commands.rb +100 -0
  9. data/lib/mindee/http/cancellation_token.rb +24 -0
  10. data/lib/mindee/http.rb +1 -0
  11. data/lib/mindee/v1/client.rb +15 -1
  12. data/lib/mindee/v2/client.rb +25 -10
  13. data/lib/mindee/v2/client_options/base_product_parameters.rb +162 -0
  14. data/lib/mindee/v2/client_options/base_search_parameters.rb +51 -0
  15. data/lib/mindee/v2/client_options.rb +4 -0
  16. data/lib/mindee/v2/http/mindee_api_v2.rb +28 -32
  17. data/lib/mindee/v2/parsing/field/field_confidence.rb +37 -2
  18. data/lib/mindee/v2/parsing/search/base_search_response.rb +47 -0
  19. data/lib/mindee/v2/parsing/search/model_webhook.rb +3 -3
  20. data/lib/mindee/v2/parsing/search/pagination_metadata.rb +1 -1
  21. data/lib/mindee/v2/parsing/search/search_models.rb +2 -1
  22. data/lib/mindee/v2/parsing/search/search_rag_document.rb +60 -0
  23. data/lib/mindee/v2/parsing/search/search_rag_documents.rb +39 -0
  24. data/lib/mindee/v2/parsing/search/search_response.rb +2 -29
  25. data/lib/mindee/v2/parsing/search.rb +5 -1
  26. data/lib/mindee/v2/product/base_product.rb +2 -2
  27. data/lib/mindee/v2/product/classification/classification_classifier.rb +1 -2
  28. data/lib/mindee/v2/product/classification/params/classification_parameters.rb +1 -1
  29. data/lib/mindee/v2/product/crop/crop_item.rb +1 -2
  30. data/lib/mindee/v2/product/crop/params/crop_parameters.rb +1 -1
  31. data/lib/mindee/v2/product/extraction/params/extraction_parameters.rb +2 -2
  32. data/lib/mindee/v2/product/ocr/params/ocr_parameters.rb +1 -1
  33. data/lib/mindee/v2/product/split/params/split_parameters.rb +1 -1
  34. data/lib/mindee/v2/product/split/split_range.rb +1 -2
  35. data/lib/mindee/v2/search/models/model_search_parameters.rb +51 -0
  36. data/lib/mindee/v2/search/models/model_search_response.rb +28 -0
  37. data/lib/mindee/v2/search/rag_documents/rag_document_search_parameters.rb +52 -0
  38. data/lib/mindee/v2/search/rag_documents/rag_document_search_response.rb +28 -0
  39. data/lib/mindee/v2/search.rb +6 -0
  40. data/lib/mindee/v2.rb +2 -0
  41. data/lib/mindee/version.rb +1 -1
  42. data/mindee.gemspec +1 -0
  43. data/sig/custom/net_http.rbs +1 -1
  44. data/sig/mindee/http/cancellation_token.rbs +15 -0
  45. data/sig/mindee/v2/client.rbs +7 -4
  46. data/sig/mindee/v2/client_options/base_product_parameters.rbs +41 -0
  47. data/sig/mindee/v2/client_options/base_search_parameters.rbs +19 -0
  48. data/sig/mindee/v2/http/mindee_api_v2.rbs +12 -6
  49. data/sig/mindee/v2/parsing/field/field_confidence.rbs +9 -0
  50. data/sig/mindee/v2/parsing/search/base_search_response.rbs +19 -0
  51. data/sig/mindee/v2/parsing/search/search_rag_document.rbs +23 -0
  52. data/sig/mindee/v2/parsing/search/search_rag_documents.rbs +16 -0
  53. data/sig/mindee/v2/parsing/search/search_response.rbs +4 -9
  54. data/sig/mindee/v2/product/base_product.rbs +3 -3
  55. data/sig/mindee/v2/product/classification/params/classification_parameters/classification_parameters.rbs +1 -1
  56. data/sig/mindee/v2/product/crop/params/crop_parameters/crop_parameters.rbs +1 -1
  57. data/sig/mindee/v2/product/extraction/params/extraction_parameters.rbs +1 -1
  58. data/sig/mindee/v2/product/ocr/params/ocr_parameters/ocr_parameters.rbs +1 -1
  59. data/sig/mindee/v2/product/split/params/split_parameters/split_parameters.rbs +1 -1
  60. data/sig/mindee/v2/search/models/model_search_parameters.rbs +22 -0
  61. data/sig/mindee/v2/search/models/model_search_response.rbs +17 -0
  62. data/sig/mindee/v2/search/rag_documents/rag_document_search_parameters.rbs +22 -0
  63. data/sig/mindee/v2/search/rag_documents/rag_document_search_response.rbs +17 -0
  64. metadata +27 -5
  65. data/.pre-commit-config.yaml +0 -36
  66. data/lib/mindee/input/base_parameters.rb +0 -156
  67. data/sig/mindee/input/base_parameters.rbs +0 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e7845fa564cb9009f33f574fe8b74b7c288e8943d07b881f44f9a028d0eb13df
4
- data.tar.gz: 9a52c3245b07e7c7ca56f1b9c6f88b8df2c5f84c8b68b2117ec31cb193dee31f
3
+ metadata.gz: 2a8d5975bde93678d55dacd3aca14239e736c643778346d6b3c350576593e086
4
+ data.tar.gz: ceadc33d7e44f574d9657124ba17683c996af4f0433c94ccba165908899fe422
5
5
  SHA512:
6
- metadata.gz: 8253351df7c79cc82245ccbdf80497104921883f373901cabe02bac65a7da9a40f4bd09fc6ae835c8051e24a2153703dceb45f88b10401f21c5cf30ec084bded
7
- data.tar.gz: f898b808b8a94074877191673cc8903b846850d1dcc42f91516709ad486fb295ff166683343f759382ae42d06fde5e42ec645d54985007f0ae9d47799b540596
6
+ metadata.gz: 566da7a6fff0b975ffbdc72901e254bf70f487fbac1f0c67b6e7095a2c510cbdf9ea2314788263c61be703e4a054f54887264a99218a5ca640c1396130347015
7
+ data.tar.gz: c1fbfff08eca29a3d0e2d64d00f8b46fd6b85a6fa50b809dc9ba89e42ba999985b00b244a4ff10d2db34e66dbce2ab714afd811b8fa06b0c40c6f8b999beae99
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Overcommit
4
+ module Hook
5
+ module PreCommit
6
+ # Local script to run gitleaks
7
+ class Gitleaks < Base
8
+ # Runs the command.
9
+ def run
10
+ result = execute(['gitleaks', 'git', '--staged', '-v', '.'])
11
+
12
+ return :pass if result.success?
13
+
14
+ [:fail, result.stdout + result.stderr]
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
data/.overcommit.yml ADDED
@@ -0,0 +1,46 @@
1
+ PreCommit:
2
+ MergeConflicts:
3
+ enabled: true
4
+
5
+ YamlSyntax:
6
+ enabled: true
7
+
8
+ TrailingWhitespace:
9
+ enabled: true
10
+
11
+ FileSize:
12
+ enabled: true
13
+ byte_limit: 1048576
14
+
15
+ RuboCop:
16
+ enabled: true
17
+ required_executable: 'bundle'
18
+ command: ['bundle', 'exec', 'rubocop', '--force-exclusion', '--no-server']
19
+
20
+ CustomScript:
21
+ enabled: true
22
+ description: 'Run Steep type checking'
23
+ required_executable: 'bundle'
24
+ command: ['bundle', 'exec', 'steep', 'check']
25
+
26
+ Gitleaks:
27
+ enabled: true
28
+ required_executable: 'gitleaks'
29
+ CommitMsg:
30
+ enabled: false
31
+ CapitalizedSubject:
32
+ enabled: false
33
+ TextWidth:
34
+ enabled: false
35
+ TrailingPeriod:
36
+ enabled: false
37
+ SingleLineSubject:
38
+ enabled: false
39
+ EmptyMessage:
40
+ enabled: false
41
+
42
+ PrePush:
43
+ BundleAudit:
44
+ enabled: true
45
+ required_executable: 'bundle'
46
+ command: ['sh', '-c', 'bundle exec bundle-audit check']
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Mindee Ruby API Library Changelog
2
2
 
3
+ ## v5.5.0 - 2026-09-30
4
+ ### Changes
5
+ * :sparkles: add support for RAG search
6
+ * :wrench: switching over from pre-commit to ruby-only solution
7
+ ### Fixes
8
+ * :bug: fix V2 hangs on GET
9
+
10
+
11
+ ## v5.4.0 - 2026-07-21
12
+ ### Changes
13
+ * :sparkles: add field confidence comparators
14
+ * :sparkles: add support for cancellation token
15
+
16
+
3
17
  ## v5.3.1 - 2026-07-15
4
18
  ### Fixes
5
19
  * :bug: fix file alias being sent as an invalid parameter
data/CONTRIBUTING.md CHANGED
@@ -68,6 +68,134 @@ Please follow these steps to have your contribution considered by the maintainer
68
68
 
69
69
  While the prerequisites above must be satisfied prior to having your pull request reviewed, the reviewer(s) may ask you to complete additional design work, tests, or other changes before your pull request can be ultimately accepted.
70
70
 
71
+ ## Development Setup
72
+
73
+ ### 1. Ruby
74
+
75
+ [`rbenv`](https://github.com/rbenv/rbenv) is the recommended way to manage Ruby versions:
76
+
77
+ ```shell
78
+ # Finalize the rbenv install (should work with both bash & zsh)
79
+ ~/.rbenv/bin/rbenv init
80
+ # And then run
81
+ eval "$(~/.rbenv/bin/rbenv init - bash)"
82
+ ```
83
+
84
+ ### 2. Clone the repository
85
+
86
+ Test data lives in a submodule, so make sure to clone recursively:
87
+
88
+ ```shell
89
+ git clone --recurse-submodules git@github.com:mindee/mindee-api-ruby.git ~/work/mindee/mindee-api-ruby
90
+ cd ~/work/mindee/mindee-api-ruby
91
+ ```
92
+
93
+ If you already cloned without `--recurse-submodules`, run `git submodule update --init --recursive`.
94
+
95
+ ### 3. Install dependencies
96
+
97
+ On Debian/Ubuntu:
98
+
99
+ ```shell
100
+ sudo apt install zlib1g-dev libssl-dev libreadline-dev libedit-dev libyaml-dev imagemagick
101
+ ```
102
+
103
+ `imagemagick` is required at runtime by `mini_magick`, the rest are needed to build Ruby itself.
104
+
105
+ ```shell
106
+ # Ruby 3.3.0 is the minimum version supported by the SDK
107
+ rbenv install 3.3.0
108
+ rbenv global 3.3.0
109
+ ```
110
+
111
+ ### 4. Install code dependencies
112
+
113
+ ```shell
114
+ bundle config set --local path vendor
115
+ bundle install
116
+ ```
117
+
118
+ ### 5. Validate the install works by running unit tests
119
+
120
+ ```shell
121
+ bundle exec rake spec
122
+ ```
123
+
124
+ ## Local Quality Checks
125
+
126
+ We use [`overcommit`](https://github.com/sds/overcommit) to run quality and security checks before
127
+ changes are committed and pushed. It is a development dependency of the gem, so `bundle install`
128
+ already installed it. The hooks are configured in [`.overcommit.yml`](.overcommit.yml), and
129
+ repository-local custom hooks live in [`.git-hooks`](.git-hooks).
130
+
131
+ The same checks run in CI, see
132
+ [`.github/workflows/_static-analysis.yml`](.github/workflows/_static-analysis.yml).
133
+
134
+ ### Install `gitleaks`
135
+
136
+ The `Gitleaks` pre-commit hook shells out to the
137
+ [`gitleaks`](https://github.com/gitleaks/gitleaks) binary, which is not a gem and must be installed
138
+ separately:
139
+
140
+ ```shell
141
+ brew install gitleaks
142
+ ```
143
+
144
+ Otherwise, grab a binary from the
145
+ [releases page](https://github.com/gitleaks/gitleaks/releases) and put it on your `PATH`.
146
+
147
+ ### Install the hooks
148
+
149
+ Run this once, after cloning:
150
+
151
+ ```shell
152
+ bundle exec overcommit --install
153
+ bundle exec overcommit --sign
154
+ bundle exec overcommit --sign pre-commit
155
+ ```
156
+
157
+ `--install` writes the git hook stubs into `.git/hooks`, and the `--sign` calls tell overcommit you
158
+ trust the current contents of `.overcommit.yml` and of the custom hooks in `.git-hooks`.
159
+
160
+ ### What runs, and when
161
+
162
+ * **pre-commit:** merge conflict markers, YAML syntax, trailing whitespace, file size, `rubocop`,
163
+ `steep check` (type checking) and `gitleaks` (secret scanning).
164
+ * **pre-push:** `bundle-audit` (dependency vulnerability check).
165
+
166
+ ### Run the hooks manually
167
+
168
+ ```shell
169
+ bundle exec overcommit --list-hooks # show which hooks are enabled
170
+ bundle exec overcommit --run # run the pre-commit hooks on all tracked files
171
+ bundle exec overcommit --run pre_push # run the pre-push hooks
172
+ bundle exec overcommit --diff main # run the pre-commit hooks on the diff against main
173
+ ```
174
+
175
+ ### Skipping hooks
176
+
177
+ Skip one or more hooks for a single run, by name:
178
+
179
+ ```shell
180
+ SKIP=Gitleaks,Steep git commit
181
+ ```
182
+
183
+ To bypass overcommit entirely (please use sparingly, CI runs the same checks):
184
+
185
+ ```shell
186
+ OVERCOMMIT_DISABLE=1 git commit
187
+ ```
188
+
189
+ ### Troubleshooting
190
+
191
+ If overcommit refuses to run and warns that the configuration or the hooks have changed, review the
192
+ diff and then re-sign:
193
+
194
+ ```shell
195
+ bundle exec overcommit --sign
196
+ bundle exec overcommit --sign pre-commit
197
+ ```
198
+
71
199
  ## Styleguides
72
200
 
73
201
  ### Git Commit Messages
data/bin/mindee.rb CHANGED
@@ -9,7 +9,10 @@ require_relative 'v2/parser'
9
9
  def root_help
10
10
  help = "Usage: mindee command [options]\n\nAvailable commands:\n"
11
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"
12
+
13
+ MindeeCLI::V2SearchCommands::V2_SEARCH_COMMANDS.each do |search_command, search_values|
14
+ help += " #{search_command.ljust(50)}#{search_values[:description]}\n"
15
+ end
13
16
 
14
17
  V2_PRODUCTS.each do |product_key, product_values|
15
18
  help += " #{product_key.ljust(50)}#{product_values[:description]}\n"
data/bin/v2/parser.rb CHANGED
@@ -2,11 +2,14 @@
2
2
 
3
3
  require 'mindee'
4
4
  require_relative 'products'
5
+ require_relative 'search_commands'
5
6
 
6
7
  module MindeeCLI
7
8
  # Mindee Command Line Interface
8
9
  # V2 CLI class.
9
10
  class V2Parser
11
+ include V2SearchCommands
12
+
10
13
  # @return [Array<String>]
11
14
  attr_reader :arguments
12
15
 
@@ -17,7 +20,10 @@ module MindeeCLI
17
20
  attr_reader :product_parser
18
21
 
19
22
  # @return [Parser]
20
- attr_reader :search_parser
23
+ attr_reader :search_models_parser
24
+
25
+ # @return [Parser]
26
+ attr_reader :search_rag_docs_parser
21
27
 
22
28
  def initialize(arguments, command_prefix: 'mindee v2')
23
29
  @arguments = arguments
@@ -26,26 +32,18 @@ module MindeeCLI
26
32
  opts.banner = "Usage: #{@command_prefix} command [options]"
27
33
  end
28
34
  @product_parser = init_product_parser
29
- @search_parser = init_search_parser
35
+ @search_models_parser = init_search_models_parser
36
+ @search_rag_docs_parser = init_search_rag_docs_parser
30
37
  end
31
38
 
32
39
  # Summarize and print the result of the command.
33
40
  # @param command [String]
34
41
  def print_result(command)
35
- if command == 'search-models'
36
- @search_parser.parse!(@arguments)
37
- result = search(@options)
38
- summarized_result = output_format == :full ? result.to_s : result.models.to_s
39
- else
40
- @product_parser[command].parse!(@arguments)
41
- @options[:file_path] = @arguments.shift
42
- if @options[:file_path].nil?
43
- warn 'file missing'
44
- abort(@product_parser[command].help)
45
- end
46
- result = send(command, @options)
47
- summarized_result = output_format == :full ? result.inference.to_s : result.inference.result.to_s
48
- end
42
+ result, summarized_result = if V2_SEARCH_COMMANDS.key?(command)
43
+ run_search(command)
44
+ else
45
+ run_product(command)
46
+ end
49
47
 
50
48
  if output_format == :raw
51
49
  puts JSON.pretty_generate(raw_payload(result.raw_http))
@@ -63,22 +61,41 @@ module MindeeCLI
63
61
  validate_command!(command)
64
62
  print_result(command)
65
63
  rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
66
- if command == 'search-models'
67
- abort("#{e.message}\n\n#{@search_parser.help}")
68
- else
69
- abort("#{e.message}\n\n#{@product_parser[command].help}")
70
- end
64
+ abort("#{e.message}\n\n#{command_parser(command).help}")
71
65
  rescue Mindee::Error::MindeeError => e
72
66
  abort(format_cli_error(e))
73
67
  end
74
68
 
75
69
  private
76
70
 
71
+ # Parse the arguments and run the given product command.
72
+ # @param command [String]
73
+ # @return [Array(Mindee::V2::Parsing::BaseResponse, String)] Response and its summary.
74
+ def run_product(command)
75
+ @product_parser[command].parse!(@arguments)
76
+ @options[:file_path] = @arguments.shift
77
+ if @options[:file_path].nil?
78
+ warn 'file missing'
79
+ abort(@product_parser[command].help)
80
+ end
81
+ result = send(command, @options)
82
+ summarized_result = output_format == :full ? result.inference.to_s : result.inference.result.to_s
83
+ [result, summarized_result]
84
+ end
85
+
86
+ # @param command [String]
87
+ # @return [OptionParser]
88
+ def command_parser(command)
89
+ V2_SEARCH_COMMANDS.key?(command) ? search_parser_for(command) : @product_parser[command]
90
+ end
91
+
77
92
  def validate_command!(command)
78
- return if V2_PRODUCTS.include?(command) || command == 'search-models'
93
+ return if V2_PRODUCTS.include?(command) || V2_SEARCH_COMMANDS.key?(command)
79
94
 
80
95
  error_msg = "#{@options_parser.help}\nAvailable commands:\n"
81
- error_msg += " #{'search-models'.ljust(50)}Search for available models for this API key\n"
96
+ V2_SEARCH_COMMANDS.each do |search_command, search_values|
97
+ error_msg += " #{search_command.ljust(50)}#{search_values[:description]}\n"
98
+ end
82
99
 
83
100
  V2_PRODUCTS.each do |product_key, product_values|
84
101
  error_msg += " #{product_key.to_s.ljust(50)}#{product_values[:description]}\n"
@@ -98,21 +115,6 @@ module MindeeCLI
98
115
  end
99
116
  end
100
117
 
101
- def init_search_parser
102
- OptionParser.new do |options_parser|
103
- options_parser.banner = "Usage: #{@command_prefix} search-models [options]"
104
- init_common_options(options_parser)
105
- options_parser.on('-n [NAME]', '--name [NAME]',
106
- 'Search for partial matches in model name. Note: case insensitive') do |v|
107
- @options[:model_name] = v
108
- end
109
- options_parser.on('-t [NAME]', '--type [NAME]',
110
- 'Search for EXACT matches in model type. Note: case sensitive') do |v|
111
- @options[:model_type] = v
112
- end
113
- end
114
- end
115
-
116
118
  def setup_specific_options(options_parser, doc_value)
117
119
  options_parser.on('-r', '--rag', 'Enable RAG') { @options[:rag] = true } if doc_value.key?(:rag)
118
120
  if doc_value.key?(:raw_text)
@@ -218,13 +220,6 @@ module MindeeCLI
218
220
  )
219
221
  end
220
222
 
221
- # @param options [Hash]
222
- # @return [Mindee::V2::Parsing::Search::SearchResponse]
223
- def search(options)
224
- mindee_client = Mindee::V2::Client.new(api_key: options[:api_key])
225
- mindee_client.search_models(options[:model_name], options[:model_type])
226
- end
227
-
228
223
  # @param options [Hash]
229
224
  # @return [Mindee::Input::InputSource]
230
225
  def setup_input_source(options)
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mindee'
4
+ require_relative 'products'
5
+
6
+ module MindeeCLI
7
+ # Search-related commands for the V2 CLI.
8
+ module V2SearchCommands
9
+ # NOTE: keep command names as string instead of symbols due to kebab-case.
10
+ V2_SEARCH_COMMANDS = {
11
+ 'search-models' => {
12
+ description: 'Search available models.',
13
+ parser: :search_models_parser,
14
+ runner: :search_models,
15
+ summary: :models,
16
+ },
17
+ 'search-rag-docs' => {
18
+ description: 'Search available RAG documents for a given model.',
19
+ parser: :search_rag_docs_parser,
20
+ runner: :search_rag_documents,
21
+ summary: :rag_documents,
22
+ },
23
+ }.freeze
24
+
25
+ private
26
+
27
+ # Parse the arguments and run the given search command.
28
+ # @param command [String]
29
+ # @return [Array(Mindee::V2::Parsing::Search::BaseSearchResponse, String)] Response and its summary.
30
+ def run_search(command)
31
+ search_command = V2_SEARCH_COMMANDS[command]
32
+ search_parser_for(command).parse!(@arguments)
33
+ result = __send__(search_command[:runner], @options)
34
+ summarized_result = output_format == :full ? result.to_s : result.public_send(search_command[:summary]).to_s
35
+ [result, summarized_result]
36
+ end
37
+
38
+ # @param command [String]
39
+ # @return [OptionParser]
40
+ def search_parser_for(command)
41
+ __send__(V2_SEARCH_COMMANDS[command][:parser])
42
+ end
43
+
44
+ # @return [OptionParser]
45
+ def init_search_models_parser
46
+ OptionParser.new do |options_parser|
47
+ options_parser.banner = "Usage: #{@command_prefix} search-models [options]"
48
+ init_common_options(options_parser)
49
+ options_parser.on('-n [NAME]', '--name [NAME]',
50
+ 'Filter by model name partial match (case insensitive).') do |v|
51
+ @options[:model_name] = v
52
+ end
53
+ options_parser.on('-m [MODEL_TYPE]', '--model-type [MODEL_TYPE]',
54
+ 'Filter by exact model type (case sensitive).',
55
+ "Available options: #{V2_PRODUCTS.keys.join(', ')}") do |v|
56
+ @options[:model_type] = v
57
+ end
58
+ end
59
+ end
60
+
61
+ # @return [OptionParser]
62
+ def init_search_rag_docs_parser
63
+ OptionParser.new do |options_parser|
64
+ options_parser.banner = "Usage: #{@command_prefix} search-rag-docs [options]"
65
+ init_common_options(options_parser)
66
+ options_parser.on('-m MODEL_ID', '--model-id MODEL_ID', 'Filter by model ID') do |v|
67
+ @options[:model_id] = v
68
+ end
69
+ options_parser.on('-f [FILENAME]', '--filename [FILENAME]',
70
+ 'Filter by file name partial match (case insensitive).') do |v|
71
+ @options[:filename] = v
72
+ end
73
+ end
74
+ end
75
+
76
+ # @param options [Hash]
77
+ # @return [Mindee::V2::Search::Models::ModelSearchResponse]
78
+ def search_models(options)
79
+ mindee_client = Mindee::V2::Client.new(api_key: options[:api_key])
80
+ mindee_client.search(
81
+ Mindee::V2::Search::Models::ModelSearchParameters.new(
82
+ name: options[:model_name],
83
+ model_type: options[:model_type]
84
+ )
85
+ )
86
+ end
87
+
88
+ # @param options [Hash]
89
+ # @return [Mindee::V2::Search::RAGDocuments::RAGDocumentSearchResponse]
90
+ def search_rag_documents(options)
91
+ mindee_client = Mindee::V2::Client.new(api_key: options[:api_key])
92
+ mindee_client.search(
93
+ Mindee::V2::Search::RAGDocuments::RAGDocumentSearchParameters.new(
94
+ model_id: options[:model_id],
95
+ filename: options[:filename]
96
+ )
97
+ )
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mindee
4
+ module HTTP
5
+ # Custom cancellation token class for polling.
6
+ class CancellationToken
7
+ private attr_reader :is_canceled
8
+
9
+ def initialize
10
+ @is_cancelled = false
11
+ end
12
+
13
+ # Cancel the token.
14
+ def cancel
15
+ @is_cancelled = true
16
+ end
17
+
18
+ # Check if the token is canceled.
19
+ def canceled?
20
+ @is_cancelled
21
+ end
22
+ end
23
+ end
24
+ end
data/lib/mindee/http.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'http/cancellation_token'
3
4
  require_relative 'http/http_error_handler'
@@ -219,6 +219,7 @@ module Mindee
219
219
  Mindee::V1::Parsing::Common::ApiResponse.new(product_class, prediction, raw_http)
220
220
  end
221
221
 
222
+ # rubocop:disable Metrics/CyclomaticComplexity
222
223
  # Enqueue a document for async parsing and automatically try to retrieve it
223
224
  #
224
225
  # @param input_source [Mindee::Input::Source::LocalInputSource, Mindee::Input::Source::URLInputSource]
@@ -247,13 +248,23 @@ module Mindee
247
248
  # * `:delay_sec` [Numeric] Delay between polling attempts. Defaults to 1.5.
248
249
  # * `:max_retries` [Integer] Maximum number of retries. Defaults to 80.
249
250
  # @param endpoint [Mindee::V1::HTTP::Endpoint] Endpoint of the API.
251
+ # @param cancellation_token [Mindee::HTTP::CancellationToken, nil] Token for cancellation.
250
252
  # @return [Mindee::V1::Parsing::Common::ApiResponse]
251
- def enqueue_and_parse(input_source, product_class, endpoint, options)
253
+ # rubocop:disable-next Metrics/PerceivedComplexity
254
+ def enqueue_and_parse(
255
+ input_source,
256
+ product_class,
257
+ endpoint,
258
+ options,
259
+ cancellation_token = nil
260
+ )
252
261
  validate_async_params(options.initial_delay_sec, options.delay_sec, options.max_retries)
253
262
  enqueue_res = enqueue(input_source, product_class, endpoint: endpoint, options: options)
254
263
  job = enqueue_res.job or raise Error::MindeeAPIError, 'Expected job to be present'
255
264
  job_id = job.id
256
265
 
266
+ raise Mindee::Error::MindeeError, 'Enqueueing of the document was canceled.' if cancellation_token&.canceled?
267
+
257
268
  sleep(options.initial_delay_sec)
258
269
  polling_attempts = 1
259
270
  logger.debug("Successfully enqueued document with job id: '#{job_id}'")
@@ -266,6 +277,8 @@ module Mindee
266
277
  # @type var valid_statuses: Array[(:waiting | :processing | :completed | :failed)]
267
278
  while valid_statuses.include?(queue_res_job.status) && polling_attempts < options.max_retries
268
279
  logger.debug("Polling server for parsing result with job id: '#{job_id}'. Attempt #{polling_attempts}")
280
+ raise Mindee::Error::MindeeError, 'Enqueueing of the document was canceled.' if cancellation_token&.canceled?
281
+
269
282
  sleep(options.delay_sec)
270
283
  queue_res = parse_queued(job_id, product_class, endpoint: endpoint)
271
284
  queue_res_job = queue_res.job or raise Error::MindeeAPIError, 'Expected job to be present'
@@ -281,6 +294,7 @@ module Mindee
281
294
  queue_res
282
295
  end
283
296
 
297
+ # rubocop:enable Metrics/CyclomaticComplexity
284
298
  # Sends a document to a workflow.
285
299
  #
286
300
  # Accepts options either as a Hash or as a WorkflowOptions struct.
@@ -37,7 +37,7 @@ module Mindee
37
37
  # @param product [Class<Mindee::V2::Product::BaseProduct>] The return class.
38
38
  # @param input_source [Mindee::Input::Source::LocalInputSource, Mindee::Input::Source::URLInputSource]
39
39
  # The source of the input document (local file or URL).
40
- # @param params [Hash, Input::BaseParameters] Parameters for the inference.
40
+ # @param params [Hash, ClientOptions::BaseProductParameters] Parameters for the inference.
41
41
  # @return [Mindee::V2::Parsing::JobResponse]
42
42
  def enqueue(
43
43
  product,
@@ -48,7 +48,7 @@ module Mindee
48
48
  normalized_params.validate_async_params
49
49
  logger.debug("Enqueueing document to model '#{normalized_params.model_id}'.")
50
50
 
51
- @mindee_api.req_post_enqueue(input_source, normalized_params)
51
+ @mindee_api.req_post_product_enqueue(input_source, normalized_params)
52
52
  end
53
53
 
54
54
  # Enqueues to an asynchronous endpoint and automatically polls for a response.
@@ -56,14 +56,17 @@ module Mindee
56
56
  # @param product [Class<Mindee::V2::Product::BaseProduct>] The return class.
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
- # @param params [Hash, Input::BaseParameters] Parameters for the inference.
59
+ # @param params [Hash, ClientOptions::BaseProductParameters] Parameters for the inference.
60
60
  # @param polling_options [Hash, PollingOptions, nil] Parameters for polling.
61
+ # @param cancellation_token [Mindee::HTTP::CancellationToken, nil] Token for cancellation.
61
62
  # @return [Parsing::BaseResponse]
63
+ # rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
62
64
  def enqueue_and_get_result(
63
65
  product,
64
66
  input_source,
65
67
  params,
66
- polling_options = nil
68
+ polling_options = nil,
69
+ cancellation_token = nil
67
70
  )
68
71
  enqueue_response = enqueue(product, input_source, params)
69
72
  normalized_params = normalize_parameters(product.params_type, params, polling_options: polling_options)
@@ -77,6 +80,8 @@ module Mindee
77
80
  job_id = enqueue_response.job.id
78
81
  logger.debug("Successfully enqueued document with job id: #{job_id}.")
79
82
 
83
+ raise Mindee::Error::MindeeError, 'Enqueueing of the document was canceled.' if cancellation_token&.canceled?
84
+
80
85
  sleep(normalized_params.polling_options.initial_delay_sec)
81
86
  retry_counter = 1
82
87
  poll_results = get_job(job_id)
@@ -94,6 +99,8 @@ module Mindee
94
99
  "Job status: #{poll_results.job.status}."
95
100
  )
96
101
 
102
+ raise Mindee::Error::MindeeError, 'Enqueueing of the document was canceled.' if cancellation_token&.canceled?
103
+
97
104
  sleep(normalized_params.polling_options.delay_sec)
98
105
  poll_results = get_job(job_id)
99
106
  retry_counter += 1
@@ -111,12 +118,20 @@ module Mindee
111
118
  "Asynchronous parsing request timed out after #{sec_count} seconds"
112
119
  end
113
120
 
114
- # Searches for a list of available models for the given API key.
115
- # @param model_name [String]
116
- # @param model_type [String]
117
- # @return [Mindee::V2::Parsing::Search::SearchResponse]
121
+ # Search for resources matching the given criteria.
122
+ # @param params [ClientOptions::BaseSearchParameters] Search parameters.
123
+ # @return [Mindee::V2::Parsing::Search::BaseSearchResponse] A search response containing the matching resources.
124
+ def search(params)
125
+ @mindee_api.req_get_search(params)
126
+ end
127
+
128
+ # Returns a list of models matching a criteria for the given API key.
129
+ # @deprecated Use {#search} instead.
130
+ # @param model_name [String, nil] Name filter.
131
+ # @param model_type [String, nil] Model type filter.
132
+ # @return [Mindee::V2::Search::Models::ModelSearchResponse]
118
133
  def search_models(model_name, model_type)
119
- @mindee_api.search_models(model_name, model_type)
134
+ search(Search::Models::ModelSearchParameters.new(name: model_name, model_type: model_type))
120
135
  end
121
136
 
122
137
  private
@@ -128,7 +143,7 @@ module Mindee
128
143
  def normalize_parameters(param_class, params, polling_options: nil)
129
144
  if params.is_a?(Hash)
130
145
  params[:polling_options] = polling_options if polling_options
131
- elsif params.is_a?(Mindee::Input::BaseParameters) && !polling_options.nil?
146
+ elsif params.is_a?(Mindee::V2::ClientOptions::BaseProductParameters) && !polling_options.nil?
132
147
  params.polling_options = polling_options
133
148
  end
134
149
  return param_class.from_hash(params: params) if params.is_a?(Hash)