runapi-kling 0.2.8 → 0.2.9

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: '06496c392220522b5dedc8acd4f71436ba22fd51df6ac685d8600fc5a5f3d02f'
4
- data.tar.gz: ba507498208a38a168ec79b1e7a1041c95101c5aa510f1ba11cd55a3cd6e4a1a
3
+ metadata.gz: d2943605c3e518ce6a424760e18be4da5a853f87b167f2b4a61688e6aa810485
4
+ data.tar.gz: b7b43a3379b6be598313bce535b399a240237eda145b4e644f11ae02709fbba7
5
5
  SHA512:
6
- metadata.gz: 361d632584c9a124c7e295bd3ae2f337f0434166ee76e13871afc5e17a96fc11e30f86802daa65724f1c8ee421cc4638ab97329cacce8dff1e14a701f12e0f89
7
- data.tar.gz: 2a4358323094f9d1d2269b857107927042707cb003df73abb7855d3305cf30d1bcf5e09bda2799dec94da92ca85fc72d5eb5ac334e448de688749ac81a16daba
6
+ metadata.gz: 7629e75af240e178d3d155d0f4d3430e5cbddeda6e34827fabdbcc0b54166d28c79633c6f2e2f385ea234ac4ed04c625d7174799ecfc60cf7376b664d83f885b
7
+ data.tar.gz: eca5d1069c584b2edcc402c053a6d0355012ec09a5294ff72a7a04abd3473d3fd5595fbb6d48260afc72369c0f0ea6f5b3a8b4bb1223f6c5509b647262f71c01
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
- # Kling AI API Ruby SDK for RunAPI
1
+ # Kling API Ruby SDK for RunAPI
2
2
 
3
- The kling ai api Ruby SDK is the language-specific package for Kling on RunAPI. Use this kling ai api package for text-to-video, image-to-video, video editing, and animation flows when your application needs JSON request bodies, task status lookup, and consistent RunAPI errors in Ruby.
3
+ The Kling Ruby SDK is the language-specific package for Kling on RunAPI. Use this package for video generation, animation, and video editing workflows when your application needs request bodies, task status lookup, and consistent RunAPI errors in Ruby.
4
4
 
5
- This kling ai api README is the Ruby package guide inside the public `kling-sdk` repository. For the repository overview, start at `../README.md`; for model details, use https://runapi.ai/models/kling; for API reference, use https://runapi.ai/docs#kling; for SDK docs, use https://runapi.ai/docs#sdk-kling.
5
+ This README is the Ruby package guide inside the public `kling-sdk` repository. For the repository overview, start at `../README.md`; for model details, use https://runapi.ai/models/kling; for API reference, use https://runapi.ai/docs#kling; for SDK docs, use https://runapi.ai/docs#sdk-kling.
6
6
 
7
7
  ## Install
8
8
 
@@ -13,13 +13,13 @@ gem install runapi-kling
13
13
  ## Quick start
14
14
 
15
15
  ```ruby
16
- require "runapi-kling"
16
+ require "runapi/kling"
17
17
 
18
18
  client = RunApi::Kling::Client.new
19
- task = client.generations.create(
19
+ task = client.text_to_video.create(
20
20
  # Pass the Kling JSON request body from https://runapi.ai/docs#kling.
21
21
  )
22
- status = client.generations.get(task.id)
22
+ status = client.text_to_video.get(task.id)
23
23
  ```
24
24
 
25
25
  Use `create` when you want to submit a task and return quickly, `get` when you need the latest task state, and `run` when a script should create and poll until completion. In web request handlers, prefer `create` plus webhook or later `get` polling so a worker is not held open.
@@ -28,7 +28,7 @@ RunAPI-generated file URLs are temporary. Download and store generated images, v
28
28
 
29
29
  ## Language notes
30
30
 
31
- Use Ruby keyword arguments and the `RunApi::Kling` error classes when building video jobs, Rails workers, or scripts. The available resources include text-to-video, image-to-video, AI avatars, V2.1/V2.5 video variants, and motion controls. Keep `RUNAPI_API_KEY` in the environment or your secret manager; never commit API keys or callback secrets.
31
+ Use Ruby keyword arguments and the `RunApi::Kling` error classes when building video jobs, Rails workers, or scripts. The available resources are `text_to_video`, `ai_avatar`, `image_to_video`, and `motion_control`. Keep `RUNAPI_API_KEY` in the environment or your secret manager; never commit API keys or callback secrets.
32
32
 
33
33
  ## Links
34
34
 
@@ -0,0 +1,277 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RunApi
4
+ module Kling
5
+ CONTRACT = {
6
+ "avatar" => {
7
+ "models" => ["kling-ai-avatar-pro", "kling-ai-avatar-standard", "kling-ai-avatar-v1-pro", "kling-v1-avatar-standard"],
8
+ "fields_by_model" => {
9
+ "kling-ai-avatar-pro" => {
10
+ "model" => {
11
+ "required" => true
12
+ },
13
+ "prompt" => {
14
+ "required" => true
15
+ },
16
+ "source_audio_url" => {
17
+ "required" => true
18
+ },
19
+ "source_image_url" => {
20
+ "required" => true
21
+ }
22
+ },
23
+ "kling-ai-avatar-standard" => {
24
+ "model" => {
25
+ "required" => true
26
+ },
27
+ "prompt" => {
28
+ "required" => true
29
+ },
30
+ "source_audio_url" => {
31
+ "required" => true
32
+ },
33
+ "source_image_url" => {
34
+ "required" => true
35
+ }
36
+ },
37
+ "kling-ai-avatar-v1-pro" => {
38
+ "model" => {
39
+ "required" => true
40
+ },
41
+ "prompt" => {
42
+ "required" => true
43
+ },
44
+ "source_audio_url" => {
45
+ "required" => true
46
+ },
47
+ "source_image_url" => {
48
+ "required" => true
49
+ }
50
+ },
51
+ "kling-v1-avatar-standard" => {
52
+ "model" => {
53
+ "required" => true
54
+ },
55
+ "prompt" => {
56
+ "required" => true
57
+ },
58
+ "source_audio_url" => {
59
+ "required" => true
60
+ },
61
+ "source_image_url" => {
62
+ "required" => true
63
+ }
64
+ }
65
+ }
66
+ },
67
+ "image-to-video" => {
68
+ "models" => ["kling-v2.1-master-image-to-video", "kling-v2.1-pro", "kling-v2.1-standard", "kling-v2.5-turbo-image-to-video-pro", "kling-v3-turbo-image-to-video"],
69
+ "fields_by_model" => {
70
+ "kling-v2.1-master-image-to-video" => {
71
+ "duration_seconds" => {
72
+ "enum" => [5, 10],
73
+ "type" => "integer"
74
+ },
75
+ "first_frame_image_url" => {
76
+ "required" => true
77
+ },
78
+ "model" => {
79
+ "required" => true
80
+ },
81
+ "prompt" => {
82
+ "required" => true
83
+ }
84
+ },
85
+ "kling-v2.1-pro" => {
86
+ "duration_seconds" => {
87
+ "enum" => [5, 10],
88
+ "type" => "integer"
89
+ },
90
+ "first_frame_image_url" => {
91
+ "required" => true
92
+ },
93
+ "model" => {
94
+ "required" => true
95
+ },
96
+ "prompt" => {
97
+ "required" => true
98
+ }
99
+ },
100
+ "kling-v2.1-standard" => {
101
+ "duration_seconds" => {
102
+ "enum" => [5, 10],
103
+ "type" => "integer"
104
+ },
105
+ "first_frame_image_url" => {
106
+ "required" => true
107
+ },
108
+ "model" => {
109
+ "required" => true
110
+ },
111
+ "prompt" => {
112
+ "required" => true
113
+ }
114
+ },
115
+ "kling-v2.5-turbo-image-to-video-pro" => {
116
+ "duration_seconds" => {
117
+ "enum" => [5, 10],
118
+ "type" => "integer"
119
+ },
120
+ "first_frame_image_url" => {
121
+ "required" => true
122
+ },
123
+ "model" => {
124
+ "required" => true
125
+ },
126
+ "prompt" => {
127
+ "required" => true
128
+ }
129
+ },
130
+ "kling-v3-turbo-image-to-video" => {
131
+ "duration_seconds" => {
132
+ "enum" => [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
133
+ "type" => "integer"
134
+ },
135
+ "first_frame_image_url" => {
136
+ "required" => true
137
+ },
138
+ "model" => {
139
+ "required" => true
140
+ },
141
+ "output_resolution" => {
142
+ "enum" => ["720p", "1080p"]
143
+ },
144
+ "prompt" => {
145
+ "required" => true,
146
+ "min" => 1,
147
+ "max" => 2500,
148
+ "length" => true
149
+ }
150
+ }
151
+ },
152
+ "rules" => [{
153
+ "when" => {
154
+ "model" => "kling-v2.1-master-image-to-video"
155
+ },
156
+ "forbidden" => ["output_resolution"]
157
+ }, {
158
+ "when" => {
159
+ "model" => "kling-v2.1-pro"
160
+ },
161
+ "forbidden" => ["output_resolution"]
162
+ }, {
163
+ "when" => {
164
+ "model" => "kling-v2.1-standard"
165
+ },
166
+ "forbidden" => ["output_resolution"]
167
+ }, {
168
+ "when" => {
169
+ "model" => "kling-v2.5-turbo-image-to-video-pro"
170
+ },
171
+ "forbidden" => ["output_resolution"]
172
+ }, {
173
+ "when" => {
174
+ "model" => "kling-v3-turbo-image-to-video"
175
+ },
176
+ "forbidden" => ["aspect_ratio", "negative_prompt", "cfg_scale", "last_frame_image_url"]
177
+ }]
178
+ },
179
+ "motion-control" => {
180
+ "models" => ["kling-3.0"],
181
+ "fields_by_model" => {
182
+ "kling-3.0" => {
183
+ "background_source" => {
184
+ "enum" => ["video", "image"]
185
+ },
186
+ "character_orientation" => {
187
+ "enum" => ["video", "image"]
188
+ },
189
+ "model" => {
190
+ "required" => true
191
+ },
192
+ "output_resolution" => {
193
+ "enum" => ["720p", "1080p"]
194
+ },
195
+ "reference_video_url" => {
196
+ "required" => true
197
+ },
198
+ "source_image_url" => {
199
+ "required" => true
200
+ }
201
+ }
202
+ }
203
+ },
204
+ "text-to-video" => {
205
+ "models" => ["kling-3.0", "kling-v2.1-master-text-to-video", "kling-v2.5-turbo-text-to-video-pro", "kling-v3-turbo-text-to-video"],
206
+ "fields_by_model" => {
207
+ "kling-3.0" => {
208
+ "aspect_ratio" => {
209
+ "enum" => ["16:9", "9:16", "1:1"]
210
+ },
211
+ "duration_seconds" => {
212
+ "enum" => [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
213
+ "type" => "integer"
214
+ },
215
+ "model" => {
216
+ "required" => true
217
+ },
218
+ "output_resolution" => {
219
+ "enum" => ["720p", "1080p", "4k"]
220
+ }
221
+ },
222
+ "kling-v2.1-master-text-to-video" => {
223
+ "aspect_ratio" => {
224
+ "enum" => ["16:9", "9:16", "1:1"]
225
+ },
226
+ "duration_seconds" => {
227
+ "enum" => [5, 10],
228
+ "type" => "integer"
229
+ },
230
+ "model" => {
231
+ "required" => true
232
+ }
233
+ },
234
+ "kling-v2.5-turbo-text-to-video-pro" => {
235
+ "aspect_ratio" => {
236
+ "enum" => ["16:9", "9:16", "1:1"]
237
+ },
238
+ "duration_seconds" => {
239
+ "enum" => [5, 10],
240
+ "type" => "integer"
241
+ },
242
+ "model" => {
243
+ "required" => true
244
+ }
245
+ },
246
+ "kling-v3-turbo-text-to-video" => {
247
+ "aspect_ratio" => {
248
+ "enum" => ["16:9", "9:16", "1:1"]
249
+ },
250
+ "duration_seconds" => {
251
+ "enum" => [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
252
+ "type" => "integer"
253
+ },
254
+ "model" => {
255
+ "required" => true
256
+ },
257
+ "output_resolution" => {
258
+ "enum" => ["720p", "1080p"]
259
+ },
260
+ "prompt" => {
261
+ "required" => true,
262
+ "min" => 1,
263
+ "max" => 2500,
264
+ "length" => true
265
+ }
266
+ }
267
+ },
268
+ "rules" => [{
269
+ "when" => {
270
+ "model" => "kling-v3-turbo-text-to-video"
271
+ },
272
+ "forbidden" => ["enable_sound", "negative_prompt", "cfg_scale", "multi_shots", "multi_prompt", "first_frame_image_url", "last_frame_image_url", "kling_elements"]
273
+ }]
274
+ }
275
+ }.freeze
276
+ end
277
+ end
@@ -21,41 +21,33 @@ module RunApi
21
21
  #
22
22
  # @param params [Hash] AI avatar parameters
23
23
  # @return [RunApi::Kling::Types::CompletedAiAvatarResponse] completed task with videos
24
- def run(**params)
25
- task = create(**params)
26
- poll_until_complete { get(task.id) }
24
+ def run(options: nil, **params)
25
+ task = create(options: options, **params)
26
+ poll_until_complete { get(task.id, options: options) }
27
27
  end
28
28
 
29
29
  # Create an AI avatar generation task.
30
30
  #
31
31
  # @param params [Hash] AI avatar parameters
32
32
  # @return [RunApi::Kling::Types::AiAvatarResponse] task creation result with id
33
- def create(**params)
33
+ def create(options: nil, **params)
34
34
  params = compact_params(params)
35
35
  validate_params!(params)
36
- request(:post, ENDPOINT, body: params)
36
+ request(:post, ENDPOINT, body: params, options: options)
37
37
  end
38
38
 
39
39
  # Get AI avatar task status by task ID.
40
40
  #
41
41
  # @param id [String] task ID
42
42
  # @return [RunApi::Kling::Types::AiAvatarResponse] current task status
43
- def get(id)
44
- request(:get, "#{ENDPOINT}/#{id}")
43
+ def get(id, options: nil)
44
+ request(:get, "#{ENDPOINT}/#{id}", options: options)
45
45
  end
46
46
 
47
47
  private
48
48
 
49
49
  def validate_params!(params)
50
- model = param(params, :model)
51
- raise Core::ValidationError, "model is required" unless model
52
- unless Types::AI_AVATAR_MODELS.include?(model)
53
- raise Core::ValidationError, "Invalid model: #{model}. Must be one of: #{Types::AI_AVATAR_MODELS.join(", ")}"
54
- end
55
-
56
- raise Core::ValidationError, "source_image_url is required" unless param(params, :source_image_url)
57
- raise Core::ValidationError, "source_audio_url is required" unless param(params, :source_audio_url)
58
- raise Core::ValidationError, "prompt is required" unless param(params, :prompt)
50
+ validate_contract!(CONTRACT["avatar"], params)
59
51
  end
60
52
  end
61
53
  end
@@ -12,6 +12,13 @@ module RunApi
12
12
 
13
13
  RESPONSE_CLASS = Types::ImageToVideoResponse
14
14
  COMPLETED_RESPONSE_CLASS = Types::CompletedImageToVideoResponse
15
+ V3_TURBO_MODEL = "kling-v3-turbo-image-to-video"
16
+ V3_TURBO_UNSUPPORTED_FIELDS = %i[
17
+ aspect_ratio
18
+ negative_prompt
19
+ cfg_scale
20
+ last_frame_image_url
21
+ ].freeze
15
22
 
16
23
  def initialize(http)
17
24
  @http = http
@@ -21,51 +28,50 @@ module RunApi
21
28
  #
22
29
  # @param params [Hash] image-to-video parameters
23
30
  # @return [RunApi::Kling::Types::CompletedImageToVideoResponse] completed task with videos
24
- def run(**params)
25
- task = create(**params)
26
- poll_until_complete { get(task.id) }
31
+ def run(options: nil, **params)
32
+ task = create(options: options, **params)
33
+ poll_until_complete { get(task.id, options: options) }
27
34
  end
28
35
 
29
36
  # Create an image-to-video task.
30
37
  #
31
38
  # @param params [Hash] image-to-video parameters
32
39
  # @return [RunApi::Kling::Types::ImageToVideoResponse] task creation result with id
33
- def create(**params)
40
+ def create(options: nil, **params)
34
41
  params = compact_params(params)
35
42
  validate_params!(params)
36
- request(:post, ENDPOINT, body: params)
43
+ request(:post, ENDPOINT, body: params, options: options)
37
44
  end
38
45
 
39
46
  # Get image-to-video task status by task ID.
40
47
  #
41
48
  # @param id [String] task ID
42
49
  # @return [RunApi::Kling::Types::ImageToVideoResponse] current task status
43
- def get(id)
44
- request(:get, "#{ENDPOINT}/#{id}")
50
+ def get(id, options: nil)
51
+ request(:get, "#{ENDPOINT}/#{id}", options: options)
45
52
  end
46
53
 
47
54
  private
48
55
 
49
56
  def validate_params!(params)
50
- model = param(params, :model)
51
- raise Core::ValidationError, "model is required" unless model
52
- unless Types::IMAGE_TO_VIDEO_MODELS.include?(model)
53
- raise Core::ValidationError, "Invalid model: #{model}. Must be one of: #{Types::IMAGE_TO_VIDEO_MODELS.join(", ")}"
54
- end
55
-
56
- raise Core::ValidationError, "prompt is required" unless param(params, :prompt)
57
- raise Core::ValidationError, "first_frame_image_url is required" unless param(params, :first_frame_image_url)
58
-
59
- duration_seconds = param(params, :duration_seconds)
60
- if duration_seconds && !Types::FIXED_DURATIONS.include?(duration_seconds)
61
- raise Core::ValidationError, "Invalid duration_seconds: #{duration_seconds}. Must be one of: #{Types::FIXED_DURATIONS.join(", ")}"
62
- end
57
+ reject_unsupported_v3_turbo_fields!(params)
58
+ validate_contract!(CONTRACT["image-to-video"], params)
63
59
 
60
+ # Bespoke: last_frame_image_url is only allowed for select models
61
+ # (model-gating, not expressible as a contract enum/required rule).
62
+ model = param(params, :model)
64
63
  last_frame_image_url = param(params, :last_frame_image_url)
65
64
  if last_frame_image_url && !%w[kling-v2.5-turbo-image-to-video-pro kling-v2.1-pro].include?(model)
66
65
  raise Core::ValidationError, "last_frame_image_url is only supported by kling-v2.5-turbo-image-to-video-pro and kling-v2.1-pro"
67
66
  end
68
67
  end
68
+
69
+ def reject_unsupported_v3_turbo_fields!(params)
70
+ return unless param(params, :model) == V3_TURBO_MODEL
71
+
72
+ field = V3_TURBO_UNSUPPORTED_FIELDS.find { |candidate| field_present?(params, candidate) }
73
+ raise Core::ValidationError, "#{field} is not supported by #{V3_TURBO_MODEL}" if field
74
+ end
69
75
  end
70
76
  end
71
77
  end
@@ -21,46 +21,33 @@ module RunApi
21
21
  #
22
22
  # @param params [Hash] motion control parameters
23
23
  # @return [RunApi::Kling::Types::CompletedMotionControlResponse] completed task with videos
24
- def run(**params)
25
- task = create(**params)
26
- poll_until_complete { get(task.id) }
24
+ def run(options: nil, **params)
25
+ task = create(options: options, **params)
26
+ poll_until_complete { get(task.id, options: options) }
27
27
  end
28
28
 
29
29
  # Create a motion control generation task.
30
30
  #
31
31
  # @param params [Hash] motion control parameters
32
32
  # @return [RunApi::Kling::Types::MotionControlResponse] task creation result with id
33
- def create(**params)
33
+ def create(options: nil, **params)
34
34
  params = compact_params(params)
35
35
  validate_params!(params)
36
- request(:post, ENDPOINT, body: params)
36
+ request(:post, ENDPOINT, body: params, options: options)
37
37
  end
38
38
 
39
39
  # Get motion control task status by task ID.
40
40
  #
41
41
  # @param id [String] task ID
42
42
  # @return [RunApi::Kling::Types::MotionControlResponse] current task status
43
- def get(id)
44
- request(:get, "#{ENDPOINT}/#{id}")
43
+ def get(id, options: nil)
44
+ request(:get, "#{ENDPOINT}/#{id}", options: options)
45
45
  end
46
46
 
47
47
  private
48
48
 
49
49
  def validate_params!(params)
50
- model = param(params, :model)
51
- raise Core::ValidationError, "model is required" unless model
52
- unless Types::MOTION_CONTROL_MODELS.include?(model)
53
- raise Core::ValidationError, "Invalid model: #{model}. Must be one of: #{Types::MOTION_CONTROL_MODELS.join(", ")}"
54
- end
55
- validate_optional!(params, :output_resolution, Types::MOTION_CONTROL_OUTPUT_RESOLUTIONS)
56
- validate_optional!(params, :character_orientation, Types::MOTION_CONTROL_CHARACTER_ORIENTATIONS)
57
- validate_optional!(params, :background_source, Types::MOTION_CONTROL_BACKGROUND_SOURCES)
58
-
59
- source_image_url = param(params, :source_image_url)
60
- raise Core::ValidationError, "source_image_url is required" unless source_image_url
61
-
62
- reference_video_url = param(params, :reference_video_url)
63
- raise Core::ValidationError, "reference_video_url is required" unless reference_video_url
50
+ validate_contract!(CONTRACT["motion-control"], params)
64
51
  end
65
52
  end
66
53
  end
@@ -12,6 +12,17 @@ module RunApi
12
12
 
13
13
  RESPONSE_CLASS = Types::TextToVideoResponse
14
14
  COMPLETED_RESPONSE_CLASS = Types::CompletedTextToVideoResponse
15
+ V3_TURBO_MODEL = "kling-v3-turbo-text-to-video"
16
+ V3_TURBO_UNSUPPORTED_FIELDS = %i[
17
+ enable_sound
18
+ negative_prompt
19
+ cfg_scale
20
+ multi_shots
21
+ multi_prompt
22
+ first_frame_image_url
23
+ last_frame_image_url
24
+ kling_elements
25
+ ].freeze
15
26
 
16
27
  def initialize(http)
17
28
  @http = http
@@ -21,38 +32,36 @@ module RunApi
21
32
  #
22
33
  # @param params [Hash] text-to-video parameters
23
34
  # @return [RunApi::Kling::Types::CompletedTextToVideoResponse] completed task with videos
24
- def run(**params)
25
- task = create(**params)
26
- poll_until_complete { get(task.id) }
35
+ def run(options: nil, **params)
36
+ task = create(options: options, **params)
37
+ poll_until_complete { get(task.id, options: options) }
27
38
  end
28
39
 
29
40
  # Create a text-to-video task.
30
41
  #
31
42
  # @param params [Hash] text-to-video parameters
32
43
  # @return [RunApi::Kling::Types::TextToVideoResponse] task creation result with id
33
- def create(**params)
44
+ def create(options: nil, **params)
34
45
  params = compact_params(params)
35
46
  validate_params!(params)
36
- request(:post, ENDPOINT, body: params)
47
+ request(:post, ENDPOINT, body: params, options: options)
37
48
  end
38
49
 
39
50
  # Get text-to-video task status by task ID.
40
51
  #
41
52
  # @param id [String] task ID
42
53
  # @return [RunApi::Kling::Types::TextToVideoResponse] current task status
43
- def get(id)
44
- request(:get, "#{ENDPOINT}/#{id}")
54
+ def get(id, options: nil)
55
+ request(:get, "#{ENDPOINT}/#{id}", options: options)
45
56
  end
46
57
 
47
58
  private
48
59
 
49
60
  def validate_params!(params)
50
- model = param(params, :model)
51
- raise Core::ValidationError, "model is required" unless model
52
- unless Types::TEXT_TO_VIDEO_MODELS.include?(model)
53
- raise Core::ValidationError, "Invalid model: #{model}. Must be one of: #{Types::TEXT_TO_VIDEO_MODELS.join(", ")}"
54
- end
61
+ reject_unsupported_v3_turbo_fields!(params)
62
+ validate_contract!(CONTRACT["text-to-video"], params)
55
63
 
64
+ # Bespoke cross-field rules the contract cannot express.
56
65
  multi_shots = param(params, :multi_shots) == true
57
66
 
58
67
  if multi_shots
@@ -64,21 +73,13 @@ module RunApi
64
73
  else
65
74
  raise Core::ValidationError, "prompt is required" unless param(params, :prompt)
66
75
  end
76
+ end
67
77
 
68
- validate_optional!(params, :output_resolution, Types::TEXT_TO_VIDEO_OUTPUT_RESOLUTIONS)
69
- validate_optional!(params, :aspect_ratio, Types::ASPECT_RATIOS)
78
+ def reject_unsupported_v3_turbo_fields!(params)
79
+ return unless param(params, :model) == V3_TURBO_MODEL
70
80
 
71
- duration_seconds = param(params, :duration_seconds)
72
- if duration_seconds
73
- dur_int = duration_seconds.to_i
74
- if model == "kling-v2.1-master-text-to-video" || model == "kling-v2.5-turbo-text-to-video-pro"
75
- unless Types::FIXED_DURATIONS.include?(duration_seconds)
76
- raise Core::ValidationError, "Invalid duration_seconds: #{duration_seconds}. Must be one of: #{Types::FIXED_DURATIONS.join(", ")}"
77
- end
78
- elsif !Types::DURATION_RANGE.cover?(dur_int)
79
- raise Core::ValidationError, "Invalid duration_seconds: #{duration_seconds}. Must be an integer between #{Types::DURATION_RANGE.min} and #{Types::DURATION_RANGE.max}"
80
- end
81
- end
81
+ field = V3_TURBO_UNSUPPORTED_FIELDS.find { |candidate| field_present?(params, candidate) }
82
+ raise Core::ValidationError, "#{field} is not supported by #{V3_TURBO_MODEL}" if field
82
83
  end
83
84
 
84
85
  def validate_multi_prompt!(multi_prompt)
@@ -4,54 +4,10 @@ module RunApi
4
4
  module Kling
5
5
  # Type definitions and constants for Kling video generation.
6
6
  module Types
7
- # Text-to-video model variants. kling-3.0 supports multi-shot, sound, and elements;
8
- # V2.x models support negative prompts and cfg_scale.
9
- TEXT_TO_VIDEO_MODELS = %w[
10
- kling-3.0
11
- kling-v2.5-turbo-text-to-video-pro
12
- kling-v2.1-master-text-to-video
13
- ].freeze
14
-
15
- # AI avatar lip-sync quality tiers, from highest to fastest.
16
- AI_AVATAR_MODELS = %w[
17
- kling-ai-avatar-pro
18
- kling-ai-avatar-standard
19
- kling-ai-avatar-v1-pro
20
- kling-v1-avatar-standard
21
- ].freeze
22
-
23
- # Image-to-video model variants. V2.5 turbo and V2.1 pro support last-frame image control.
24
- IMAGE_TO_VIDEO_MODELS = %w[
25
- kling-v2.5-turbo-image-to-video-pro
26
- kling-v2.1-pro
27
- kling-v2.1-standard
28
- kling-v2.1-master-image-to-video
29
- ].freeze
30
-
31
- # Output resolution options. 4k is highest quality but slowest.
32
- TEXT_TO_VIDEO_OUTPUT_RESOLUTIONS = %w[720p 1080p 4k].freeze
33
-
34
- MOTION_CONTROL_MODELS = %w[kling-3.0].freeze
35
-
36
- MOTION_CONTROL_OUTPUT_RESOLUTIONS = %w[720p 1080p].freeze
37
-
38
- # Whether the character faces the direction from the video or the image.
39
- MOTION_CONTROL_CHARACTER_ORIENTATIONS = %w[video image].freeze
40
-
41
- # Whether the background comes from the reference video or the subject image.
42
- MOTION_CONTROL_BACKGROUND_SOURCES = %w[video image].freeze
43
-
44
- ASPECT_RATIOS = %w[16:9 9:16 1:1].freeze
45
-
46
- # Duration range for kling-3.0 (seconds).
47
- DURATION_RANGE = (3..15)
48
-
49
- # Per-shot duration range in multi-shot mode (seconds).
7
+ # Per-shot duration range in multi-shot mode (seconds). Bespoke constant for
8
+ # the multi_prompt[] nested-array validation, which the contract cannot express.
50
9
  MULTI_PROMPT_DURATION_RANGE = (1..12)
51
10
 
52
- # Fixed duration options for V2.x models (seconds).
53
- FIXED_DURATIONS = [5, 10].freeze
54
-
55
11
  # Maximum character length for each multi-shot prompt segment.
56
12
  MULTI_PROMPT_MAX_LENGTH = 500
57
13
 
data/lib/runapi/kling.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "runapi/core"
4
4
  require_relative "kling/types"
5
+ require_relative "kling/contract_gen"
5
6
  require_relative "kling/resources/text_to_video"
6
7
  require_relative "kling/resources/ai_avatar"
7
8
  require_relative "kling/resources/image_to_video"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: runapi-kling
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.2.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - RunAPI
@@ -15,18 +15,18 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 0.2.6
18
+ version: 0.2.11
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: 0.2.6
26
- description: The kling ai api Ruby SDK is the language-specific package for Kling
27
- on RunAPI. Use this kling ai api package for text-to-video, image-to-video, video
28
- editing, and animation flows when your application needs JSON request bodies, task
29
- status lookup, and consistent RunAPI errors in Ruby.
25
+ version: 0.2.11
26
+ description: The Kling Ruby SDK is the language-specific package for Kling on RunAPI.
27
+ Use this package for video generation, animation, and video editing workflows when
28
+ your application needs request bodies, task status lookup, and consistent RunAPI
29
+ errors in Ruby.
30
30
  email:
31
31
  - contact@runapi.ai
32
32
  executables: []
@@ -39,6 +39,7 @@ files:
39
39
  - lib/runapi-kling.rb
40
40
  - lib/runapi/kling.rb
41
41
  - lib/runapi/kling/client.rb
42
+ - lib/runapi/kling/contract_gen.rb
42
43
  - lib/runapi/kling/resources/ai_avatar.rb
43
44
  - lib/runapi/kling/resources/image_to_video.rb
44
45
  - lib/runapi/kling/resources/motion_control.rb
@@ -48,9 +49,11 @@ homepage: https://runapi.ai/models/kling
48
49
  licenses:
49
50
  - Apache-2.0
50
51
  metadata:
52
+ runapi_slug: kling
51
53
  homepage_uri: https://runapi.ai/models/kling
52
54
  documentation_uri: https://github.com/runapi-ai/kling-sdk/blob/main/ruby/README.md
53
55
  source_code_uri: https://github.com/runapi-ai/kling-sdk
56
+ bug_tracker_uri: https://github.com/runapi-ai/kling-sdk/issues
54
57
  changelog_uri: https://github.com/runapi-ai/kling-sdk/blob/main/CHANGELOG.md
55
58
  rdoc_options: []
56
59
  require_paths:
@@ -68,5 +71,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
71
  requirements: []
69
72
  rubygems_version: 4.0.10
70
73
  specification_version: 4
71
- summary: Kling AI API Ruby SDK for RunAPI
74
+ summary: Kling API Ruby SDK for RunAPI
72
75
  test_files: []