mindee 5.4.0 → 5.6.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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/.betterleaks.toml +15 -0
  3. data/.editorconfig +1 -1
  4. data/CHANGELOG.md +14 -0
  5. data/CONTRIBUTING.md +88 -0
  6. data/bin/mindee.rb +4 -1
  7. data/bin/v1/products.rb +0 -6
  8. data/bin/v2/parser.rb +40 -45
  9. data/bin/v2/search_commands.rb +100 -0
  10. data/lib/mindee/v1/client.rb +1 -75
  11. data/lib/mindee/v1/http.rb +0 -1
  12. data/lib/mindee/v1/product.rb +0 -3
  13. data/lib/mindee/v2/client.rb +62 -36
  14. data/lib/mindee/v2/client_options/base_product_parameters.rb +162 -0
  15. data/lib/mindee/v2/client_options/base_search_parameters.rb +51 -0
  16. data/lib/mindee/v2/client_options.rb +4 -0
  17. data/lib/mindee/v2/http/mindee_api_v2.rb +59 -78
  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 +5 -5
  28. data/lib/mindee/v2/product/classification/params/classification_parameters.rb +1 -1
  29. data/lib/mindee/v2/product/crop/crop_item.rb +5 -5
  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 +5 -5
  35. data/lib/mindee/v2/search/models/model_search_parameters.rb +54 -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 -1
  43. data/prek.toml +45 -0
  44. data/sig/custom/net_http.rbs +1 -1
  45. data/sig/mindee/v1/client.rbs +1 -15
  46. data/sig/mindee/v2/client.rbs +11 -4
  47. data/sig/mindee/v2/client_options/base_product_parameters.rbs +41 -0
  48. data/sig/mindee/v2/client_options/base_search_parameters.rbs +19 -0
  49. data/sig/mindee/v2/http/mindee_api_v2.rbs +19 -15
  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/classification_classifier.rbs +1 -1
  56. data/sig/mindee/v2/product/classification/params/classification_parameters/classification_parameters.rbs +1 -1
  57. data/sig/mindee/v2/product/crop/crop_item.rbs +1 -1
  58. data/sig/mindee/v2/product/crop/params/crop_parameters/crop_parameters.rbs +1 -1
  59. data/sig/mindee/v2/product/extraction/params/extraction_parameters.rbs +1 -1
  60. data/sig/mindee/v2/product/ocr/params/ocr_parameters/ocr_parameters.rbs +1 -1
  61. data/sig/mindee/v2/product/split/params/split_parameters/split_parameters.rbs +1 -1
  62. data/sig/mindee/v2/product/split/split_range.rbs +1 -1
  63. data/sig/mindee/v2/search/models/model_search_parameters.rbs +22 -0
  64. data/sig/mindee/v2/search/models/model_search_response.rbs +17 -0
  65. data/sig/mindee/v2/search/rag_documents/rag_document_search_parameters.rbs +22 -0
  66. data/sig/mindee/v2/search/rag_documents/rag_document_search_response.rbs +17 -0
  67. metadata +28 -32
  68. data/.pre-commit-config.yaml +0 -36
  69. data/docs/code_samples/bank_account_details_v1.txt +0 -24
  70. data/docs/code_samples/barcode_reader_v1.txt +0 -24
  71. data/docs/code_samples/idcard_fr_v1.txt +0 -24
  72. data/docs/code_samples/workflow_execution.txt +0 -28
  73. data/lib/mindee/input/base_parameters.rb +0 -156
  74. data/lib/mindee/v1/http/workflow_endpoint.rb +0 -93
  75. data/lib/mindee/v1/product/barcode_reader/barcode_reader_v1.rb +0 -47
  76. data/lib/mindee/v1/product/barcode_reader/barcode_reader_v1_document.rb +0 -47
  77. data/lib/mindee/v1/product/barcode_reader/barcode_reader_v1_page.rb +0 -38
  78. data/lib/mindee/v1/product/fr/bank_account_details/bank_account_details_v1.rb +0 -49
  79. data/lib/mindee/v1/product/fr/bank_account_details/bank_account_details_v1_document.rb +0 -49
  80. data/lib/mindee/v1/product/fr/bank_account_details/bank_account_details_v1_page.rb +0 -40
  81. data/lib/mindee/v1/product/fr/id_card/id_card_v1.rb +0 -49
  82. data/lib/mindee/v1/product/fr/id_card/id_card_v1_document.rb +0 -106
  83. data/lib/mindee/v1/product/fr/id_card/id_card_v1_page.rb +0 -57
  84. data/sig/mindee/input/base_parameters.rbs +0 -36
  85. data/sig/mindee/v1/http/workflow_endpoint.rbs +0 -22
  86. data/sig/mindee/v1/product/barcode_reader/barcode_reader_v1.rbs +0 -13
  87. data/sig/mindee/v1/product/barcode_reader/barcode_reader_v1_document.rbs +0 -16
  88. data/sig/mindee/v1/product/barcode_reader/barcode_reader_v1_page.rbs +0 -17
  89. data/sig/mindee/v1/product/fr/bank_account_details/bank_account_details_v1.rbs +0 -15
  90. data/sig/mindee/v1/product/fr/bank_account_details/bank_account_details_v1_document.rbs +0 -19
  91. data/sig/mindee/v1/product/fr/bank_account_details/bank_account_details_v1_page.rbs +0 -19
  92. data/sig/mindee/v1/product/fr/id_card/id_card_v1.rbs +0 -15
  93. data/sig/mindee/v1/product/fr/id_card/id_card_v1_document.rbs +0 -26
  94. data/sig/mindee/v1/product/fr/id_card/id_card_v1_page.rbs +0 -20
@@ -18,26 +18,11 @@ module Mindee
18
18
  @mindee_api = Mindee::V2::HTTP::MindeeApiV2.new(api_key: api_key)
19
19
  end
20
20
 
21
- # Retrieves a result from a given queue or URL to the result.
22
- # @param product [Class<Mindee::V2::Product::BaseProduct>] The return class.
23
- # @param resource [String] ID of the inference or URL to the result.
24
- # @return [Mindee::V2::Parsing::BaseResponse]
25
- def get_result(product, resource)
26
- @mindee_api.req_get_result(product, resource)
27
- end
28
-
29
- # Retrieves an inference from a given queue or URL to the job.
30
- # @param job_id [String] ID of the job.
31
- # @return [Mindee::V2::Parsing::JobResponse]
32
- def get_job(job_id)
33
- @mindee_api.req_get_job(job_id)
34
- end
35
-
36
- # Enqueue a document for async parsing.
21
+ # Send a file to the asynchronous processing queue for inference.
37
22
  # @param product [Class<Mindee::V2::Product::BaseProduct>] The return class.
38
23
  # @param input_source [Mindee::Input::Source::LocalInputSource, Mindee::Input::Source::URLInputSource]
39
24
  # The source of the input document (local file or URL).
40
- # @param params [Hash, Input::BaseParameters] Parameters for the inference.
25
+ # @param params [Hash, ClientOptions::BaseProductParameters] Parameters for the inference.
41
26
  # @return [Mindee::V2::Parsing::JobResponse]
42
27
  def enqueue(
43
28
  product,
@@ -48,19 +33,51 @@ module Mindee
48
33
  normalized_params.validate_async_params
49
34
  logger.debug("Enqueueing document to model '#{normalized_params.model_id}'.")
50
35
 
51
- @mindee_api.req_post_enqueue(input_source, normalized_params)
36
+ @mindee_api.req_post_product_enqueue(input_source, normalized_params)
37
+ end
38
+
39
+ # Get the status of an inference that was previously enqueued.
40
+ # Can be used for polling.
41
+ # @param url [String] HTTPS URL to the job.
42
+ # @return [Mindee::V2::Parsing::JobResponse]
43
+ def get_job_by_url(url)
44
+ @mindee_api.req_get_job_by_url(url)
45
+ end
46
+
47
+ # Get the result of an inference that was previously enqueued.
48
+ # @param product [Class<Mindee::V2::Product::BaseProduct>] The return class.
49
+ # @param url [String] HTTPS URL to the result.
50
+ # @return [Mindee::V2::Parsing::BaseResponse]
51
+ def get_result_by_url(product, url)
52
+ @mindee_api.req_get_result_by_url(product, url)
53
+ end
54
+
55
+ # Get the result of an inference that was previously enqueued.
56
+ # Prefer using `get_result_by_url` using the result URL returned by the Job.
57
+ # @param product [Class<Mindee::V2::Product::BaseProduct>] The return class.
58
+ # @param resource [String] ID of the inference or URL to the result.
59
+ # @return [Mindee::V2::Parsing::BaseResponse]
60
+ def get_result(product, resource)
61
+ @mindee_api.req_get_result_by_id(product, resource)
52
62
  end
53
63
 
54
- # Enqueues to an asynchronous endpoint and automatically polls for a response.
55
- #
64
+ # Get the status of an inference that was previously enqueued.
65
+ # Prefer using `get_job_by_url` with the polling URL returned by enqueue.
66
+ # @param job_id [String] ID of the job.
67
+ # @return [Mindee::V2::Parsing::JobResponse]
68
+ def get_job(job_id)
69
+ @mindee_api.req_get_job_by_id(job_id)
70
+ end
71
+
72
+ # Send a file to the inference queue and return the results when complete.
56
73
  # @param product [Class<Mindee::V2::Product::BaseProduct>] The return class.
57
74
  # @param input_source [Mindee::Input::Source::LocalInputSource, Mindee::Input::Source::URLInputSource]
58
75
  # The source of the input document (local file or URL).
59
- # @param params [Hash, Input::BaseParameters] Parameters for the inference.
76
+ # @param params [Hash, ClientOptions::BaseProductParameters] Parameters for the inference.
60
77
  # @param polling_options [Hash, PollingOptions, nil] Parameters for polling.
61
78
  # @param cancellation_token [Mindee::HTTP::CancellationToken, nil] Token for cancellation.
62
79
  # @return [Parsing::BaseResponse]
63
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
80
+ # rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
64
81
  def enqueue_and_get_result(
65
82
  product,
66
83
  input_source,
@@ -84,29 +101,31 @@ module Mindee
84
101
 
85
102
  sleep(normalized_params.polling_options.initial_delay_sec)
86
103
  retry_counter = 1
87
- poll_results = get_job(job_id)
104
+ polling_url = enqueue_response.job.polling_url
105
+
106
+ job_response = get_job_by_url(polling_url)
88
107
 
89
108
  while retry_counter < normalized_params.polling_options.max_retries
90
- if poll_results.job.status == 'Failed'
109
+ if job_response.job.status == 'Failed'
91
110
  break
92
- elsif !poll_results.job.result_url.nil?
93
- return get_result(product, poll_results.job.result_url)
111
+ elsif !job_response.job.result_url.nil?
112
+ return get_result_by_url(product, job_response.job.result_url)
94
113
  end
95
114
 
96
115
  logger.debug(
97
116
  "Successfully enqueued inference with job id: #{job_id}.\n" \
98
117
  "Attempt n°#{retry_counter}/#{normalized_params.polling_options.max_retries}.\n" \
99
- "Job status: #{poll_results.job.status}."
118
+ "Job status: #{job_response.job.status}."
100
119
  )
101
120
 
102
121
  raise Mindee::Error::MindeeError, 'Enqueueing of the document was canceled.' if cancellation_token&.canceled?
103
122
 
104
123
  sleep(normalized_params.polling_options.delay_sec)
105
- poll_results = get_job(job_id)
124
+ job_response = get_job_by_url(polling_url)
106
125
  retry_counter += 1
107
126
  end
108
127
 
109
- error = poll_results.job.error
128
+ error = job_response.job.error
110
129
  unless error.nil?
111
130
  err_to_raise = Mindee::Error::MindeeHTTPErrorV2.new(error)
112
131
  # NOTE: purposefully decoupled from the line above, otherwise rubocop thinks `error` is a `message` param.
@@ -117,14 +136,21 @@ module Mindee
117
136
  raise Mindee::Error::MindeeError,
118
137
  "Asynchronous parsing request timed out after #{sec_count} seconds"
119
138
  end
120
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
121
139
 
122
- # Searches for a list of available models for the given API key.
123
- # @param model_name [String]
124
- # @param model_type [String]
125
- # @return [Mindee::V2::Parsing::Search::SearchResponse]
140
+ # Search for resources matching the given criteria.
141
+ # @param params [ClientOptions::BaseSearchParameters] Search parameters.
142
+ # @return [Mindee::V2::Parsing::Search::BaseSearchResponse] A search response containing the matching resources.
143
+ def search(params)
144
+ @mindee_api.req_get_search(params)
145
+ end
146
+
147
+ # Returns a list of models matching a criteria for the given API key.
148
+ # @deprecated Use {#search} instead.
149
+ # @param model_name [String, nil] Name filter.
150
+ # @param model_type [String, nil] Model type filter.
151
+ # @return [Mindee::V2::Search::Models::ModelSearchResponse]
126
152
  def search_models(model_name, model_type)
127
- @mindee_api.search_models(model_name, model_type)
153
+ search(Search::Models::ModelSearchParameters.new(name: model_name, model_type: model_type))
128
154
  end
129
155
 
130
156
  private
@@ -136,7 +162,7 @@ module Mindee
136
162
  def normalize_parameters(param_class, params, polling_options: nil)
137
163
  if params.is_a?(Hash)
138
164
  params[:polling_options] = polling_options if polling_options
139
- elsif params.is_a?(Mindee::Input::BaseParameters) && !polling_options.nil?
165
+ elsif params.is_a?(Mindee::V2::ClientOptions::BaseProductParameters) && !polling_options.nil?
140
166
  params.polling_options = polling_options
141
167
  end
142
168
  return param_class.from_hash(params: params) if params.is_a?(Hash)
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mindee
4
+ module V2
5
+ module ClientOptions
6
+ # Base class for parameters accepted by all V2 endpoints.
7
+ class BaseProductParameters
8
+ # @return [String] Model ID to use for the inference. Required.
9
+ attr_reader :model_id
10
+
11
+ # @return [String, nil] Optional: a free-form string to tag the request with your own identifier.
12
+ # For example, an internal document ID, reference number, or database key.
13
+ # If set, it will be included in the job and result responses.
14
+ attr_reader :file_alias
15
+
16
+ # @return [Array<String>, nil] Webhook IDs to call after all processing is finished.
17
+ # If empty, no webhooks will be used.
18
+ attr_reader :webhook_ids
19
+
20
+ # @return [Input::PollingOptions] Options for polling. Set only if having timeout issues.
21
+ attr_reader :polling_options
22
+
23
+ # @return [Boolean, nil] Whether to close the file after parsing.
24
+ attr_reader :close_file
25
+
26
+ # @param [String] model_id ID of the model
27
+ # @param [String, nil] file_alias File alias, if applicable.
28
+ # @param [Array<String>, nil] webhook_ids List of webhook IDs to propagate the API response to.
29
+ # @param [Hash, Input::PollingOptions, nil] polling_options Options for polling. Set only if having timeout
30
+ # issues.
31
+ # @param [Boolean, nil] close_file Whether to close the file after parsing.
32
+ def initialize(
33
+ model_id,
34
+ file_alias: nil,
35
+ webhook_ids: nil,
36
+ polling_options: nil,
37
+ close_file: true
38
+ )
39
+ raise Error::MindeeInputError, 'Model ID is required.' if model_id.nil? || model_id.empty?
40
+
41
+ @model_id = model_id
42
+ @file_alias = file_alias
43
+ @webhook_ids = webhook_ids || []
44
+ @polling_options = get_clean_polling_options(polling_options)
45
+ @close_file = close_file.nil? || close_file
46
+ end
47
+
48
+ # Sets polling options after normalizing hash inputs.
49
+ # @param [Hash, Input::PollingOptions, nil] polling_options
50
+ # @return [Input::PollingOptions]
51
+ def polling_options=(polling_options)
52
+ @polling_options = get_clean_polling_options(polling_options)
53
+ end
54
+
55
+ # @return [String] Slug for the endpoint.
56
+ def self.slug
57
+ if self == BaseProductParameters
58
+ raise NotImplementedError, 'Cannot access `slug` directly on the BaseProductParameters class.'
59
+ end
60
+
61
+ ''
62
+ end
63
+
64
+ # @return [String] Slug for the endpoint.
65
+ def slug
66
+ self.class.slug
67
+ end
68
+
69
+ # Load from a hash
70
+ # @param [Hash] params Parameters to provide as a hash.
71
+ # @return [BaseProductParameters]
72
+ def self.from_hash(params: {})
73
+ load_from_hash(params: params)
74
+ new(
75
+ params[:model_id],
76
+ file_alias: params[:file_alias],
77
+ webhook_ids: params[:webhook_ids],
78
+ polling_options: params[:polling_options],
79
+ close_file: params[:close_file]
80
+ )
81
+ end
82
+
83
+ # Loads a prediction from a Hash.
84
+ # @param [Hash] params Parameters to provide as a hash.
85
+ # @return [Hash]
86
+ def self.load_from_hash(params: {})
87
+ params.transform_keys!(&:to_sym)
88
+
89
+ if params.empty? || params[:model_id].nil? || params[:model_id].empty?
90
+ raise Error::MindeeInputError, 'Model ID is required.'
91
+ end
92
+
93
+ polling_options_input = params.fetch(:page_options, Input::PollingOptions.new)
94
+ if polling_options_input.is_a?(Hash)
95
+ polling_options_input = polling_options_input.transform_keys(&:to_sym)
96
+ Input::PollingOptions.new(
97
+ initial_delay_sec: polling_options_input.fetch(:initial_delay_sec, 2.0),
98
+ delay_sec: polling_options_input.fetch(:delay_sec, 1.5),
99
+ max_retries: polling_options_input.fetch(:max_retries, 80)
100
+ )
101
+ end
102
+ params
103
+ end
104
+
105
+ # Appends base form data to the provided array.
106
+ # @param [Array] form_data Array of form fields
107
+ # @return [Array]
108
+ def append_form_data(form_data)
109
+ form_data.push(['alias', @file_alias]) if @file_alias
110
+ webhook_ids = @webhook_ids || []
111
+ form_data.push(['webhook_ids', webhook_ids.join(',')]) unless @webhook_ids.nil? || webhook_ids.empty?
112
+ form_data
113
+ end
114
+
115
+ # Validates the parameters for async auto-polling
116
+ def validate_async_params
117
+ min_delay_sec = 1
118
+ min_initial_delay_sec = 1
119
+ min_retries = 2
120
+
121
+ if @polling_options.delay_sec < min_delay_sec
122
+ raise ArgumentError,
123
+ "Cannot set auto-poll delay to less than #{min_delay_sec} second(s)"
124
+ end
125
+ if @polling_options.initial_delay_sec < min_initial_delay_sec
126
+ raise ArgumentError,
127
+ "Cannot set initial parsing delay to less than #{min_initial_delay_sec} second(s)"
128
+ end
129
+ return unless @polling_options.max_retries < min_retries
130
+
131
+ raise ArgumentError,
132
+ "Cannot set auto-poll retries to less than #{min_retries}"
133
+ end
134
+
135
+ private
136
+
137
+ # Cleans a proper polling options object potentially from a hash.
138
+ # @param [Hash, Input::PollingOptions, nil] polling_options Polling options.
139
+ # @return [Input::PollingOptions] Valid polling options object.
140
+ def get_clean_polling_options(polling_options)
141
+ return Input::PollingOptions.new if polling_options.is_a?(Input::PollingOptions)
142
+
143
+ if polling_options.is_a?(Hash)
144
+ polling_options = polling_options.transform_keys(&:to_sym)
145
+ output_polling_options = Input::PollingOptions.new(
146
+ initial_delay_sec: polling_options.fetch(:initial_delay_sec, 2.0),
147
+ delay_sec: polling_options.fetch(:delay_sec, 1.5),
148
+ max_retries: polling_options.fetch(:max_retries, 80)
149
+ )
150
+ else
151
+ output_polling_options = if polling_options.is_a?(Input::PollingOptions)
152
+ polling_options || Input::PollingOptions.new
153
+ else
154
+ Input::PollingOptions.new
155
+ end
156
+ end
157
+ output_polling_options
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mindee
4
+ module V2
5
+ module ClientOptions
6
+ # Base parameters for searches.
7
+ class BaseSearchParameters
8
+ # @return [Integer, nil] 1-based page index.
9
+ attr_reader :page
10
+ # @return [Integer, nil] Number of items per page.
11
+ attr_reader :per_page
12
+
13
+ # @param page [Integer, nil] 1-based page index.
14
+ # @param per_page [Integer, nil] Number of items per page.
15
+ def initialize(page: nil, per_page: nil)
16
+ @page = page
17
+ @per_page = per_page
18
+ end
19
+
20
+ # Gets the request parameters for the search request.
21
+ # @return [Hash{String => String, Array<String>}]
22
+ def request_parameters
23
+ params = {} # : Hash[String, String | Array[String]]
24
+ params['page'] = @page.to_s unless @page.nil?
25
+ params['per_page'] = @per_page.to_s unless @per_page.nil?
26
+ params
27
+ end
28
+
29
+ # @return [String] Slug of searchable resources.
30
+ def self.slug
31
+ raise NotImplementedError, 'Subclasses must implement the `slug` class method'
32
+ end
33
+
34
+ # @return [String] Slug of searchable resources.
35
+ def slug
36
+ self.class.slug
37
+ end
38
+
39
+ # @return [Class<Mindee::V2::Parsing::Search::BaseSearchResponse>] Response class for the search.
40
+ def self.response_class
41
+ raise NotImplementedError, 'Subclasses must implement the `response_class` class method'
42
+ end
43
+
44
+ # @return [Class<Mindee::V2::Parsing::Search::BaseSearchResponse>] Response class for the search.
45
+ def response_class
46
+ self.class.response_class
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'client_options/base_product_parameters'
4
+ require_relative 'client_options/base_search_parameters'
@@ -17,13 +17,13 @@ module Mindee
17
17
  @settings = ApiV2Settings.new(api_key: api_key)
18
18
  end
19
19
 
20
- # Sends a file to the queue.
20
+ # Send a file to the asynchronous processing queue for inference processing.
21
21
  #
22
22
  # @param input_source [Input::Source::LocalInputSource, Input::Source::URLInputSource]
23
- # @param params [Input::BaseParameters]
23
+ # @param params [ClientOptions::BaseProductParameters]
24
24
  # @return [Mindee::V2::Parsing::JobResponse]
25
25
  # @raise [Mindee::Error::MindeeHttpErrorV2]
26
- def req_post_enqueue(input_source, params)
26
+ def req_post_product_enqueue(input_source, params)
27
27
  @settings.check_api_key
28
28
  response = enqueue(
29
29
  input_source,
@@ -33,52 +33,53 @@ module Mindee
33
33
  end
34
34
 
35
35
  # Retrieves a result from a given queue.
36
- # @param product [Class<Mindee::V2::Product::BaseProduct>] The return class.
37
- # @param resource [String] ID of the inference or URL to the result.
36
+ # @param product [Class<Mindee::V2::Product::BaseProduct>]
37
+ # @param inference_id [String] ID of the inference or URL to the result.
38
38
  # @return [Mindee::V2::Parsing::BaseResponse]
39
- def req_get_result(product, resource)
40
- return req_get_result_url(product.response_type, resource) if uri?(resource)
41
-
42
- @settings.check_api_key
43
- response = result_req_get(
44
- resource,
45
- product
46
- )
47
- product.response_type.new(process_response(response))
39
+ def req_get_result_by_id(product, inference_id)
40
+ req_get_result_by_url(product, "#{@settings.base_url}/v2/products/#{product.slug}/results/#{inference_id}")
48
41
  end
49
42
 
50
43
  # Retrieves a queued job.
51
44
  #
52
45
  # @param job_id [String] ID of the job or URL to the job.
53
46
  # @return [Mindee::V2::Parsing::JobResponse]
54
- def req_get_job(job_id)
47
+ def req_get_job_by_id(job_id)
48
+ req_get_job_by_url("#{@settings.base_url}/v2/jobs/#{job_id}")
49
+ end
50
+
51
+ # Retrieves a queued job from its polling URL.
52
+ #
53
+ # @param url [String] HTTPS URL to the job.
54
+ # @return [Mindee::V2::Parsing::JobResponse]
55
+ def req_get_job_by_url(url)
56
+ validate_https_url!(url)
55
57
  @settings.check_api_key
56
- response = poll("#{@settings.base_url}/v2/jobs/#{job_id}")
58
+ response = poll(url)
57
59
  Mindee::V2::Parsing::JobResponse.new(process_response(response))
58
60
  end
59
61
 
60
- # Retrieves a list of models.
61
- # @param model_name [String, nil]
62
- # @param model_type [String, nil]
63
- # @return [Mindee::V2::Parsing::Search::SearchResponse]
64
- def search_models(model_name, model_type)
65
- Mindee::V2::Parsing::Search::SearchResponse.new(process_response(req_get_search_models(model_name,
66
- model_type)))
62
+ # Retrieves a result from its URL.
63
+ #
64
+ # @param product [Class<Mindee::V2::Product::BaseProduct>]
65
+ # @param url [String] HTTPS URL to the result.
66
+ # @return [Mindee::V2::Parsing::BaseResponse]
67
+ def req_get_result_by_url(product, url)
68
+ validate_https_url!(url)
69
+ @settings.check_api_key
70
+ response = poll(url)
71
+ product.response_type.new(process_response(response))
67
72
  end
68
73
 
69
- private
70
-
71
- # Retrieves a list of models.
72
- # @param model_name [String, nil]
73
- # @param model_type [String, nil]
74
- # @return [Net::HTTPResponse]
75
- def req_get_search_models(model_name, model_type)
76
- url = "#{@settings.base_url}/v2/search/models"
77
- uri = URI(url)
74
+ # Retrieves a list of resources with the given criteria.
75
+ # @param params [ClientOptions::BaseSearchParameters] Search parameters.
76
+ # @return [Mindee::V2::Parsing::Search::BaseSearchResponse] A search response containing the matching
77
+ # resources.
78
+ def req_get_search(params)
79
+ @settings.check_api_key
80
+ uri = URI("#{@settings.base_url}/v2/search/#{params.slug}")
78
81
 
79
- query_params = {} # @type var query_params: Hash[Symbol, String | nil]
80
- query_params[:name] = model_name if model_name
81
- query_params[:model_type] = model_type if model_type
82
+ query_params = params.request_parameters
82
83
  uri.query = URI.encode_www_form(query_params) unless query_params.empty?
83
84
 
84
85
  headers = {
@@ -86,43 +87,27 @@ module Mindee
86
87
  'User-Agent' => @settings.user_agent,
87
88
  }
88
89
  req = Net::HTTP::Get.new(uri, headers)
89
- req['Transfer-Encoding'] = 'chunked'
90
90
 
91
- Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, read_timeout: @settings.request_timeout) do |http|
92
- return http.request(req)
91
+ response = Net::HTTP.start(uri.hostname, uri.port,
92
+ use_ssl: true,
93
+ open_timeout: @settings.request_timeout,
94
+ read_timeout: @settings.request_timeout) do |http|
95
+ http.request(req)
93
96
  end
94
- raise Mindee::Error::MindeeError, 'Could not resolve server response.'
97
+ params.response_class.new(process_response(response))
95
98
  end
96
99
 
97
- # @param resource [String] Resource to check.
98
- # @return [Boolean]
99
- def uri?(resource)
100
- uri = URI.parse(resource)
101
- throw Mindee::Error::MindeeError, 'HTTP is not supported.' if uri.scheme == 'http'
102
- uri.scheme == 'https'
103
- rescue URI::BadURIError, URI::InvalidURIError
104
- false
105
- end
106
-
107
- # Retrieves a queued job.
108
- #
109
- # @param url [String]
110
- # @return [Mindee::V2::Parsing::JobResponse]
111
- def req_get_job_url(url)
112
- @settings.check_api_key
113
- response = poll(url)
114
- Mindee::V2::Parsing::JobResponse.new(process_response(response))
115
- end
100
+ private
116
101
 
117
- # Retrieves a queued job.
102
+ # Validates that a URL uses HTTPS and includes a host.
118
103
  #
119
- # @param result_class [Class<Mindee::V2::Parsing::BaseResponse>]
120
104
  # @param url [String]
121
- # @return [Mindee::V2::Parsing::BaseResponse]
122
- def req_get_result_url(result_class, url)
123
- @settings.check_api_key
124
- response = poll(url)
125
- result_class.new(process_response(response))
105
+ # @return [void]
106
+ def validate_https_url!(url)
107
+ uri = URI.parse(url)
108
+ raise Mindee::Error::MindeeError, "Invalid URL: #{url}" unless uri.scheme == 'https' && !uri.host.to_s.empty?
109
+ rescue URI::BadURIError, URI::InvalidURIError
110
+ raise Mindee::Error::MindeeError, "Invalid URL: #{url}"
126
111
  end
127
112
 
128
113
  # Converts an HTTP response to a parsed response object.
@@ -155,23 +140,16 @@ module Mindee
155
140
  'User-Agent' => @settings.user_agent,
156
141
  }
157
142
  req = Net::HTTP::Get.new(uri, headers)
158
- req['Transfer-Encoding'] = 'chunked'
159
143
 
160
- Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, read_timeout: @settings.request_timeout) do |http|
144
+ Net::HTTP.start(uri.hostname, uri.port,
145
+ use_ssl: true,
146
+ open_timeout: @settings.request_timeout,
147
+ read_timeout: @settings.request_timeout) do |http|
161
148
  return http.request(req)
162
149
  end
163
150
  raise Mindee::Error::MindeeError, 'Could not resolve server response.'
164
151
  end
165
152
 
166
- # Polls the API for the result of an inference.
167
- #
168
- # @param queue_id [String] ID of the queue.
169
- # @param product [Class<Mindee::V2::Product::BaseProduct>] The return class.
170
- # @return [Net::HTTPResponse]
171
- def result_req_get(queue_id, product)
172
- poll("#{@settings.base_url}/v2/products/#{product.slug}/results/#{queue_id}")
173
- end
174
-
175
153
  # Handle parameters for the enqueue form
176
154
  # @param form_data [Array] Array of form fields
177
155
  # @param params [V2::Product::Extraction::Params::ExtractionParameters] Inference options.
@@ -191,7 +169,7 @@ module Mindee
191
169
  end
192
170
 
193
171
  # @param input_source [Mindee::Input::Source::LocalInputSource, Mindee::Input::Source::URLInputSource]
194
- # @param params [Input::BaseParameters] Inference options.
172
+ # @param params [ClientOptions::BaseProductParameters] Inference options.
195
173
  # @return [Net::HTTPResponse, nil]
196
174
  def enqueue(input_source, params)
197
175
  uri = URI("#{@settings.base_url}/v2/products/#{params.slug}/enqueue")
@@ -218,7 +196,10 @@ module Mindee
218
196
  req.set_form(form_data, 'multipart/form-data')
219
197
  req['Transfer-Encoding'] = 'chunked'
220
198
 
221
- Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, read_timeout: @settings.request_timeout) do |http|
199
+ Net::HTTP.start(uri.hostname, uri.port,
200
+ use_ssl: true,
201
+ open_timeout: @settings.request_timeout,
202
+ read_timeout: @settings.request_timeout) do |http|
222
203
  return http.request(req)
223
204
  end
224
205
  raise Mindee::Error::MindeeError, 'Could not resolve server response.'
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mindee
4
+ module V2
5
+ module Parsing
6
+ module Search
7
+ # Base class for search responses.
8
+ class BaseSearchResponse < CommonResponse
9
+ # Pagination metadata.
10
+ # @return [Mindee::V2::Parsing::Search::PaginationMetadata]
11
+ attr_reader :pagination
12
+
13
+ # @param http_response [Hash] The parsed JSON payload from the API.
14
+ def initialize(http_response)
15
+ super
16
+
17
+ @pagination = PaginationMetadata.new(http_response['pagination'])
18
+ end
19
+
20
+ # Lines composing the response-specific body (header + items).
21
+ # @return [Array<String>]
22
+ def body_lines
23
+ raise NotImplementedError, 'body_lines must be implemented in subclasses'
24
+ end
25
+
26
+ # Pagination metadata (Obsolete).
27
+ # @deprecated Use {#pagination} instead.
28
+ # @return [Mindee::V2::Parsing::Search::PaginationMetadata]
29
+ def pagination_metadata
30
+ pagination
31
+ end
32
+
33
+ # String representation of the search response.
34
+ # @return [String]
35
+ def to_s
36
+ lines = body_lines
37
+ lines.push('Pagination Metadata')
38
+ lines.push('###################')
39
+ lines.push(@pagination.to_s)
40
+
41
+ lines.join("\n")
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -4,7 +4,7 @@ module Mindee
4
4
  module V2
5
5
  module Parsing
6
6
  module Search
7
- # Individual webhook information.
7
+ # Information about a model's webhook.
8
8
  class ModelWebhook
9
9
  # @return [String] ID of the webhook.
10
10
  attr_reader :id
@@ -15,14 +15,14 @@ module Mindee
15
15
  # @return [String] URL of the webhook.
16
16
  attr_reader :url
17
17
 
18
- # @param payload [Hash] The parsed JSON payload mapping to the search model.
18
+ # @param payload [Hash] The parsed JSON payload mapping to the webhook.
19
19
  def initialize(payload)
20
20
  @id = payload['id']
21
21
  @name = payload['name']
22
22
  @url = payload['url']
23
23
  end
24
24
 
25
- # String representation of the model.
25
+ # String representation of the webhook.
26
26
  # @return [String]
27
27
  def to_s
28
28
  [
@@ -4,7 +4,7 @@ module Mindee
4
4
  module V2
5
5
  module Parsing
6
6
  module Search
7
- # Pagination Metadata data associated with model search.
7
+ # Pagination metadata associated with searches.
8
8
  class PaginationMetadata
9
9
  # @return [Integer] Number of items per page.
10
10
  attr_reader :per_page