pangea-sdk 0.0.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 (63) hide show
  1. checksums.yaml +7 -0
  2. data/.ignore +2 -0
  3. data/README.md +1 -0
  4. data/lib/pangea/client.rb +51 -0
  5. data/lib/pangea/errors.rb +113 -0
  6. data/lib/pangea/internal/transport/base_client.rb +346 -0
  7. data/lib/pangea/internal/transport/pooled_net_requester.rb +191 -0
  8. data/lib/pangea/internal/type/array_of.rb +119 -0
  9. data/lib/pangea/internal/type/base_model.rb +289 -0
  10. data/lib/pangea/internal/type/boolean.rb +44 -0
  11. data/lib/pangea/internal/type/converter.rb +228 -0
  12. data/lib/pangea/internal/type/hash_of.rb +166 -0
  13. data/lib/pangea/internal/type/request_parameters.rb +38 -0
  14. data/lib/pangea/internal/type/union.rb +66 -0
  15. data/lib/pangea/internal/type/unknown.rb +50 -0
  16. data/lib/pangea/internal/util.rb +429 -0
  17. data/lib/pangea/internal.rb +12 -0
  18. data/lib/pangea/models/ai_guard/classification_result.rb +33 -0
  19. data/lib/pangea/models/ai_guard/hardening_result.rb +27 -0
  20. data/lib/pangea/models/ai_guard/language_result.rb +20 -0
  21. data/lib/pangea/models/ai_guard/malicious_entity_result.rb +42 -0
  22. data/lib/pangea/models/ai_guard/prompt_injection_result.rb +33 -0
  23. data/lib/pangea/models/ai_guard/redact_entity_result.rb +43 -0
  24. data/lib/pangea/models/ai_guard/single_entity_result.rb +21 -0
  25. data/lib/pangea/models/ai_guard/text_guard_message_param.rb +19 -0
  26. data/lib/pangea/models/ai_guard/text_guard_params.rb +24 -0
  27. data/lib/pangea/models/ai_guard/text_guard_result.rb +308 -0
  28. data/lib/pangea/models/ai_guard/topic_result.rb +33 -0
  29. data/lib/pangea/models/pangea_response.rb +67 -0
  30. data/lib/pangea/request_options.rb +35 -0
  31. data/lib/pangea/services/ai_guard.rb +62 -0
  32. data/lib/pangea/version.rb +5 -0
  33. data/lib/pangea.rb +45 -0
  34. data/manifest.yaml +6 -0
  35. data/rbi/lib/pangea/client.rbi +25 -0
  36. data/rbi/lib/pangea/internal/internal.rbi +28 -0
  37. data/rbi/lib/pangea/internal/transport/base_client.rbi +18 -0
  38. data/rbi/lib/pangea/internal/type/array_of.rbi +66 -0
  39. data/rbi/lib/pangea/internal/type/base_model.rbi +33 -0
  40. data/rbi/lib/pangea/internal/type/boolean.rbi +46 -0
  41. data/rbi/lib/pangea/internal/type/converter.rbi +38 -0
  42. data/rbi/lib/pangea/internal/type/request_parameters.rbi +20 -0
  43. data/rbi/lib/pangea/internal/type/union.rbi +21 -0
  44. data/rbi/lib/pangea/internal/type/unknown.rbi +20 -0
  45. data/rbi/lib/pangea/internal.rbi +7 -0
  46. data/rbi/lib/pangea/models/ai_guard/text_guard_message_param.rbi +15 -0
  47. data/rbi/lib/pangea/models/ai_guard/text_guard_result.rbi +13 -0
  48. data/rbi/lib/pangea/models/pangea_response.rbi +31 -0
  49. data/rbi/lib/pangea/request_options.rbi +17 -0
  50. data/rbi/lib/pangea/services/ai_guard.rbi +28 -0
  51. data/rbi/lib/pangea/version.rbi +5 -0
  52. data/sig/pangea/client.rbs +12 -0
  53. data/sig/pangea/internal/transport/base_client.rbs +14 -0
  54. data/sig/pangea/internal/type/base_model.rbs +12 -0
  55. data/sig/pangea/internal/type/boolean.rbs +10 -0
  56. data/sig/pangea/internal/type/converter.rbs +9 -0
  57. data/sig/pangea/internal/type/request_parameters.rbs +15 -0
  58. data/sig/pangea/models/pangea_response.rbs +12 -0
  59. data/sig/pangea/models/text_guard_result.rbs +19 -0
  60. data/sig/pangea/request_options.rbs +34 -0
  61. data/sig/pangea/services/ai_guard.rbs +12 -0
  62. data/sig/pangea/version.rbs +3 -0
  63. metadata +126 -0
@@ -0,0 +1,228 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pangea
4
+ module Internal
5
+ module Type
6
+ module Converter
7
+ # @api private
8
+ #
9
+ # @param value [Object]
10
+ #
11
+ # @param state [Hash{Symbol=>Object}] .
12
+ #
13
+ # @option state [Boolean, :strong] :strictness
14
+ #
15
+ # @option state [Hash{Symbol=>Object}] :exactness
16
+ #
17
+ # @option state [Integer] :branched
18
+ #
19
+ # @return [Object]
20
+ def coerce(value, state:) = (raise NotImplementedError)
21
+
22
+ # @api private
23
+ #
24
+ # @param value [Object]
25
+ #
26
+ # @param state [Hash{Symbol=>Object}] .
27
+ #
28
+ # @option state [Boolean] :can_retry
29
+ #
30
+ # @return [Object]
31
+ def dump(value, state:)
32
+ case value
33
+ in Array
34
+ value.map { Pangea::Internal::Type::Unknown.dump(_1, state: state) }
35
+ in Hash
36
+ value.transform_values { Pangea::Internal::Type::Unknown.dump(_1, state: state) }
37
+ in Pangea::Internal::Type::BaseModel
38
+ value.class.dump(value, state: state)
39
+ in StringIO
40
+ value.string
41
+ in Pathname | IO
42
+ state[:can_retry] = false if value.is_a?(IO)
43
+ Pangea::Internal::Util::SerializationAdapter.new(value)
44
+ else
45
+ value
46
+ end
47
+ end
48
+
49
+ class << self
50
+ # @api private
51
+ #
52
+ # Based on `target`, transform `value` into `target`, to the extent possible:
53
+ #
54
+ # 1. if the given `value` conforms to `target` already, return the given `value`
55
+ # 2. if it's possible and safe to convert the given `value` to `target`, then the
56
+ # converted value
57
+ # 3. otherwise, the given `value` unaltered
58
+ #
59
+ # @param target [Pangea::Internal::Type::Converter, Class]
60
+ #
61
+ # @param value [Object]
62
+ #
63
+ # @param state [Hash{Symbol=>Object}] The `strictness` is one of `true`, `false`, or `:strong`. This informs the
64
+ # coercion strategy when we have to decide between multiple possible conversion
65
+ # targets:
66
+ #
67
+ # - `true`: the conversion must be exact, with minimum coercion.
68
+ # - `false`: the conversion can be approximate, with some coercion.
69
+ # - `:strong`: the conversion must be exact, with no coercion, and raise an error
70
+ # if not possible.
71
+ #
72
+ # The `exactness` is `Hash` with keys being one of `yes`, `no`, or `maybe`. For
73
+ # any given conversion attempt, the exactness will be updated based on how closely
74
+ # the value recursively matches the target type:
75
+ #
76
+ # - `yes`: the value can be converted to the target type with minimum coercion.
77
+ # - `maybe`: the value can be converted to the target type with some reasonable
78
+ # coercion.
79
+ # - `no`: the value cannot be converted to the target type.
80
+ #
81
+ # See implementation below for more details.
82
+ #
83
+ # @option state [Boolean, :strong] :strictness
84
+ #
85
+ # @option state [Hash{Symbol=>Object}] :exactness
86
+ #
87
+ # @option state [Integer] :branched
88
+ #
89
+ # @return [Object]
90
+ def coerce(
91
+ target,
92
+ value,
93
+ state: {strictness: true, exactness: {yes: 0, no: 0, maybe: 0}, branched: 0}
94
+ )
95
+ # rubocop:disable Lint/SuppressedException
96
+ # rubocop:disable Metrics/BlockNesting
97
+
98
+ strictness, exactness = state.fetch_values(:strictness, :exactness)
99
+
100
+ case target
101
+ in Pangea::Internal::Type::Converter
102
+ return target.coerce(value, state: state)
103
+ in Class
104
+ if value.is_a?(target)
105
+ exactness[:yes] += 1
106
+ return value
107
+ end
108
+
109
+ case target
110
+ in -> { _1 <= NilClass }
111
+ exactness[value.nil? ? :yes : :maybe] += 1
112
+ return nil
113
+ in -> { _1 <= Integer }
114
+ if value.is_a?(Integer)
115
+ exactness[:yes] += 1
116
+ return value
117
+ elsif strictness == :strong && Integer(value, exception: false) != value
118
+ message = "no implicit conversion of #{value.class} into #{target.inspect}"
119
+ raise value.is_a?(Numeric) ? ArgumentError.new(message) : TypeError.new(message)
120
+ else
121
+ Kernel.then do
122
+ return Integer(value).tap { exactness[:maybe] += 1 }
123
+ rescue ArgumentError, TypeError
124
+ end
125
+ end
126
+ in -> { _1 <= Float }
127
+ if value.is_a?(Numeric)
128
+ exactness[:yes] += 1
129
+ return Float(value)
130
+ elsif strictness == :strong
131
+ message = "no implicit conversion of #{value.class} into #{target.inspect}"
132
+ raise TypeError.new(message)
133
+ else
134
+ Kernel.then do
135
+ return Float(value).tap { exactness[:maybe] += 1 }
136
+ rescue ArgumentError, TypeError
137
+ end
138
+ end
139
+ in -> { _1 <= String }
140
+ case value
141
+ in String | Symbol | Numeric
142
+ exactness[value.is_a?(Numeric) ? :maybe : :yes] += 1
143
+ return value.to_s
144
+ in StringIO
145
+ exactness[:yes] += 1
146
+ return value.string
147
+ else
148
+ if strictness == :strong
149
+ message = "no implicit conversion of #{value.class} into #{target.inspect}"
150
+ raise TypeError.new(message)
151
+ end
152
+ end
153
+ in -> { _1 <= Date || _1 <= Time }
154
+ Kernel.then do
155
+ return target.parse(value).tap { exactness[:yes] += 1 }
156
+ rescue ArgumentError, TypeError => e
157
+ raise e if strictness == :strong
158
+ end
159
+ in -> { _1 <= StringIO } if value.is_a?(String)
160
+ exactness[:yes] += 1
161
+ return StringIO.new(value.b)
162
+ else
163
+ end
164
+ in Symbol
165
+ case value
166
+ in Symbol | String
167
+ if value.to_sym == target
168
+ exactness[:yes] += 1
169
+ return target
170
+ else
171
+ exactness[:maybe] += 1
172
+ return value
173
+ end
174
+ else
175
+ if strictness == :strong
176
+ message = "cannot convert non-matching #{value.class} into #{target.inspect}"
177
+ raise ArgumentError.new(message)
178
+ end
179
+ end
180
+ else
181
+ end
182
+
183
+ exactness[:no] += 1
184
+ value
185
+
186
+ # rubocop:enable Metrics/BlockNesting
187
+ # rubocop:enable Lint/SuppressedException
188
+ end
189
+
190
+ # @api private
191
+ #
192
+ # @param target [Pangea::Internal::Type::Converter, Class]
193
+ #
194
+ # @param value [Object]
195
+ #
196
+ # @param state [Hash{Symbol=>Object}] .
197
+ #
198
+ # @option state [Boolean] :can_retry
199
+ #
200
+ # @return [Object]
201
+ def dump(target, value, state: {can_retry: true})
202
+ case target
203
+ in Pangea::Internal::Type::Converter
204
+ target.dump(value, state: state)
205
+ else
206
+ Pangea::Internal::Type::Unknown.dump(value, state: state)
207
+ end
208
+ end
209
+
210
+ def type_info(spec)
211
+ case spec
212
+ in Proc
213
+ spec
214
+ in Hash
215
+ type_info(spec.slice(:const, :enum, :union).first&.last)
216
+ in true | false
217
+ -> { Pangea::Internal::Type::Boolean }
218
+ in Pangea::Internal::Type::Converter | Class | Symbol
219
+ -> { spec }
220
+ in NilClass | Integer | Float
221
+ -> { spec.class }
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pangea
4
+ module Internal
5
+ module Type
6
+ # @api private
7
+ #
8
+ # @abstract
9
+ #
10
+ # @generic Elem
11
+ #
12
+ # Hash of items of a given type.
13
+ class HashOf
14
+ include Pangea::Internal::Type::Converter
15
+
16
+ private_class_method :new
17
+
18
+ # @overload [](type_info, spec = {})
19
+ #
20
+ # @param type_info [Hash{Symbol=>Object}, Proc, Pangea::Internal::Type::Converter, Class]
21
+ #
22
+ # @param spec [Hash{Symbol=>Object}] .
23
+ #
24
+ # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
25
+ #
26
+ # @option spec [Proc] :enum
27
+ #
28
+ # @option spec [Proc] :union
29
+ #
30
+ # @option spec [Boolean] :"nil?"
31
+ def self.[](...) = new(...)
32
+
33
+ # @param other [Object]
34
+ #
35
+ # @return [Boolean]
36
+ def ===(other)
37
+ type = item_type
38
+ case other
39
+ in Hash
40
+ other.all? do |key, val|
41
+ case [key, val]
42
+ in [Symbol | String, ^type]
43
+ true
44
+ else
45
+ false
46
+ end
47
+ end
48
+ else
49
+ false
50
+ end
51
+ end
52
+
53
+ # @param other [Object]
54
+ #
55
+ # @return [Boolean]
56
+ def ==(other)
57
+ # rubocop:disable Layout/LineLength
58
+ other.is_a?(Pangea::Internal::Type::HashOf) && other.nilable? == nilable? && other.item_type == item_type
59
+ # rubocop:enable Layout/LineLength
60
+ end
61
+
62
+ # @return [Integer]
63
+ def hash = [self.class, item_type].hash
64
+
65
+ # @api private
66
+ #
67
+ # @param value [Hash{Object=>Object}, Object]
68
+ #
69
+ # @param state [Hash{Symbol=>Object}] .
70
+ #
71
+ # @option state [Boolean, :strong] :strictness
72
+ #
73
+ # @option state [Hash{Symbol=>Object}] :exactness
74
+ #
75
+ # @option state [Integer] :branched
76
+ #
77
+ # @return [Hash{Symbol=>Object}, Object]
78
+ def coerce(value, state:)
79
+ exactness = state.fetch(:exactness)
80
+
81
+ unless value.is_a?(Hash)
82
+ exactness[:no] += 1
83
+ return value
84
+ end
85
+
86
+ target = item_type
87
+ exactness[:yes] += 1
88
+ value
89
+ .to_h do |key, val|
90
+ k = key.is_a?(String) ? key.to_sym : key
91
+ v =
92
+ case [nilable?, val]
93
+ in [true, nil]
94
+ exactness[:yes] += 1
95
+ nil
96
+ else
97
+ Pangea::Internal::Type::Converter.coerce(target, val, state: state)
98
+ end
99
+
100
+ exactness[:no] += 1 unless k.is_a?(Symbol)
101
+ [k, v]
102
+ end
103
+ end
104
+
105
+ # @api private
106
+ #
107
+ # @param value [Hash{Object=>Object}, Object]
108
+ #
109
+ # @param state [Hash{Symbol=>Object}] .
110
+ #
111
+ # @option state [Boolean] :can_retry
112
+ #
113
+ # @return [Hash{Symbol=>Object}, Object]
114
+ def dump(value, state:)
115
+ target = item_type
116
+ if value.is_a?(Hash)
117
+ value.transform_values do
118
+ Pangea::Internal::Type::Converter.dump(target, _1, state: state)
119
+ end
120
+ else
121
+ super
122
+ end
123
+ end
124
+
125
+ # @api private
126
+ #
127
+ # @return [generic<Elem>]
128
+ protected def item_type = @item_type_fn.call
129
+
130
+ # @api private
131
+ #
132
+ # @return [Boolean]
133
+ protected def nilable? = @nilable
134
+
135
+ # @api private
136
+ #
137
+ # @param type_info [Hash{Symbol=>Object}, Proc, Pangea::Internal::Type::Converter, Class]
138
+ #
139
+ # @param spec [Hash{Symbol=>Object}] .
140
+ #
141
+ # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
142
+ #
143
+ # @option spec [Proc] :enum
144
+ #
145
+ # @option spec [Proc] :union
146
+ #
147
+ # @option spec [Boolean] :"nil?"
148
+ def initialize(type_info, spec = {})
149
+ @item_type_fn = Pangea::Internal::Type::Converter.type_info(type_info || spec)
150
+ @nilable = spec.fetch(:nil?, false)
151
+ end
152
+
153
+ # @api private
154
+ #
155
+ # @param depth [Integer]
156
+ #
157
+ # @return [String]
158
+ def inspect(depth: 0)
159
+ items = Pangea::Internal::Type::Converter.inspect(item_type, depth: depth.succ)
160
+
161
+ "#{self.class}[#{[items, nilable? ? 'nil' : nil].compact.join(' | ')}]"
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pangea
4
+ module Internal
5
+ module Type
6
+ # @api private
7
+ module RequestParameters
8
+ def self.included(mod)
9
+ raise ArgumentError.new(mod) unless mod <= Pangea::Internal::Type::BaseModel
10
+
11
+ mod.optional(:request_options, Pangea::RequestOptions)
12
+ end
13
+
14
+ # @api private
15
+ module Converter
16
+ # @api private
17
+ def dump_request(params)
18
+ state = {can_retry: true}
19
+ case (dumped = dump(params, state: state))
20
+ in Hash
21
+ options = Pangea::Internal::Util.coerce_hash(dumped[:request_options])
22
+ request_options =
23
+ case [options, state.fetch(:can_retry)]
24
+ in [Hash | nil, false]
25
+ {**options.to_h, max_retries: 0}
26
+ else
27
+ options
28
+ end
29
+ [dumped.except(:request_options), request_options]
30
+ else
31
+ [dumped, nil]
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pangea
4
+ module Internal
5
+ module Type
6
+ # @api private
7
+ module Union
8
+ include Pangea::Internal::Type::Converter
9
+
10
+ # @api private
11
+ #
12
+ # All of the specified variant info for this union.
13
+ #
14
+ # @return [Array<Array(Symbol, Proc)>]
15
+ private def known_variants = (@known_variants ||= [])
16
+
17
+ # @api private
18
+ #
19
+ # @param key [Symbol, Hash{Symbol=>Object}, Proc, Pangea::Internal::Type::Converter, Class]
20
+ #
21
+ # @param spec [Hash{Symbol=>Object}, Proc, Pangea::Internal::Type::Converter, Class] .
22
+ #
23
+ # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
24
+ #
25
+ # @option spec [Proc] :enum
26
+ #
27
+ # @option spec [Proc] :union
28
+ #
29
+ # @option spec [Boolean] :"nil?"
30
+ private def variant(key, spec = nil)
31
+ variant_info =
32
+ case key
33
+ in Symbol
34
+ [key, Pangea::Internal::Type::Converter.type_info(spec)]
35
+ in Proc | Pangea::Internal::Type::Converter | Class | Hash
36
+ [nil, Pangea::Internal::Type::Converter.type_info(key)]
37
+ end
38
+
39
+ known_variants << variant_info
40
+ end
41
+
42
+ # @api private
43
+ #
44
+ # @param value [Object]
45
+ #
46
+ # @param state [Hash{Symbol=>Object}] .
47
+ #
48
+ # @option state [Boolean] :can_retry
49
+ #
50
+ # @return [Object]
51
+ def dump(value, state:)
52
+ if (target = resolve_variant(value))
53
+ return Pangea::Internal::Type::Converter.dump(target, value, state: state)
54
+ end
55
+
56
+ known_variants.each do
57
+ target = _2.call
58
+ return Pangea::Internal::Type::Converter.dump(target, value, state: state) if target === value
59
+ end
60
+
61
+ super
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pangea
4
+ module Internal
5
+ module Type
6
+ # @api private
7
+ #
8
+ # @abstract
9
+ class Unknown
10
+ extend Pangea::Internal::Type::Converter
11
+
12
+ private_class_method :new
13
+
14
+ # rubocop:disable Lint/UnusedMethodArgument
15
+
16
+ # @param other [Object]
17
+ #
18
+ # @return [Boolean]
19
+ def self.===(other) = true
20
+
21
+ # rubocop:enable Lint/UnusedMethodArgument
22
+
23
+ # @param other [Object]
24
+ #
25
+ # @return [Boolean]
26
+ def self.==(other) = other.is_a?(Class) && other <= Pangea::Internal::Type::Unknown
27
+
28
+ class << self
29
+ # @api private
30
+ #
31
+ # @param value [Object]
32
+ #
33
+ # @param state [Hash{Symbol=>Object}] .
34
+ #
35
+ # @option state [Boolean, :strong] :strictness
36
+ #
37
+ # @option state [Hash{Symbol=>Object}] :exactness
38
+ #
39
+ # @option state [Integer] :branched
40
+ #
41
+ # @return [Object]
42
+ def coerce(value, state:)
43
+ state.fetch(:exactness)[:yes] += 1
44
+ value
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end