vidspotai-shared 1.0.124 → 1.0.126

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 (153) hide show
  1. package/lib/globals/aiModels/enums.d.ts +38 -0
  2. package/lib/globals/aiModels/enums.d.ts.map +1 -1
  3. package/lib/globals/aiModels/enums.js +49 -1
  4. package/lib/globals/aiModels/index.d.ts.map +1 -1
  5. package/lib/globals/aiModels/index.js +2 -0
  6. package/lib/globals/aiModels/providers/alibaba.d.ts.map +1 -1
  7. package/lib/globals/aiModels/providers/alibaba.js +460 -53
  8. package/lib/globals/aiModels/providers/bytedance.d.ts.map +1 -1
  9. package/lib/globals/aiModels/providers/bytedance.js +221 -39
  10. package/lib/globals/aiModels/providers/google.d.ts.map +1 -1
  11. package/lib/globals/aiModels/providers/google.js +178 -32
  12. package/lib/globals/aiModels/providers/kling.d.ts.map +1 -1
  13. package/lib/globals/aiModels/providers/kling.js +86 -12
  14. package/lib/globals/aiModels/providers/minimax.d.ts.map +1 -1
  15. package/lib/globals/aiModels/providers/minimax.js +77 -0
  16. package/lib/globals/aiModels/providers/openai.d.ts.map +1 -1
  17. package/lib/globals/aiModels/providers/openai.js +12 -0
  18. package/lib/globals/aiModels/providers/pixverse.d.ts.map +1 -1
  19. package/lib/globals/aiModels/providers/pixverse.js +101 -28
  20. package/lib/globals/aiModels/providers/runway.d.ts.map +1 -1
  21. package/lib/globals/aiModels/providers/runway.js +450 -24
  22. package/lib/globals/aiModels/providers/xai.d.ts +4 -0
  23. package/lib/globals/aiModels/providers/xai.d.ts.map +1 -0
  24. package/lib/globals/aiModels/providers/xai.js +72 -0
  25. package/lib/globals/aiModels/tierHelpers.d.ts +10 -0
  26. package/lib/globals/aiModels/tierHelpers.d.ts.map +1 -1
  27. package/lib/globals/aiModels/tierHelpers.js +48 -7
  28. package/lib/globals/aiModels/types.d.ts +21 -0
  29. package/lib/globals/aiModels/types.d.ts.map +1 -1
  30. package/lib/models/image.model.d.ts +24 -0
  31. package/lib/models/image.model.d.ts.map +1 -1
  32. package/lib/models/image.model.js +12 -0
  33. package/lib/models/index.d.ts +1 -0
  34. package/lib/models/index.d.ts.map +1 -1
  35. package/lib/models/index.js +1 -0
  36. package/lib/models/klingElement.model.d.ts +52 -0
  37. package/lib/models/klingElement.model.d.ts.map +1 -0
  38. package/lib/models/klingElement.model.js +24 -0
  39. package/lib/models/user.model.d.ts +7 -1
  40. package/lib/models/user.model.d.ts.map +1 -1
  41. package/lib/models/video.model.d.ts +11 -0
  42. package/lib/models/video.model.d.ts.map +1 -1
  43. package/lib/schemas/videoPlan.schema.d.ts +88 -0
  44. package/lib/schemas/videoPlan.schema.d.ts.map +1 -1
  45. package/lib/schemas/videoPlan.schema.js +27 -1
  46. package/lib/services/agent/executor/visual.d.ts.map +1 -1
  47. package/lib/services/agent/executor/visual.js +40 -2
  48. package/lib/services/agent/mentionedRefs.d.ts.map +1 -1
  49. package/lib/services/agent/mentionedRefs.js +4 -1
  50. package/lib/services/agent/planner/structuralRules.d.ts.map +1 -1
  51. package/lib/services/agent/planner/structuralRules.js +8 -3
  52. package/lib/services/agent/poster/posterAgent.schema.d.ts +3 -3
  53. package/lib/services/agent/providerFallback/chains.d.ts +25 -0
  54. package/lib/services/agent/providerFallback/chains.d.ts.map +1 -1
  55. package/lib/services/agent/providerFallback/chains.js +59 -5
  56. package/lib/services/agent/repair/strategies/llmRepair.strategy.d.ts.map +1 -1
  57. package/lib/services/agent/repair/strategies/llmRepair.strategy.js +2 -0
  58. package/lib/services/agent/tools/animateImage.tool.d.ts +31 -0
  59. package/lib/services/agent/tools/animateImage.tool.d.ts.map +1 -1
  60. package/lib/services/agent/tools/animateImage.tool.js +10 -3
  61. package/lib/services/agent/tools/generateImage.tool.d.ts +8 -4
  62. package/lib/services/agent/tools/generateImage.tool.d.ts.map +1 -1
  63. package/lib/services/agent/tools/generateImage.tool.js +24 -7
  64. package/lib/services/agent/tools/generateVideo.tool.d.ts +32 -0
  65. package/lib/services/agent/tools/generateVideo.tool.d.ts.map +1 -1
  66. package/lib/services/agent/tools/generateVideo.tool.js +37 -9
  67. package/lib/services/agent/tools/planVideo.tool.d.ts +19 -0
  68. package/lib/services/agent/tools/planVideo.tool.d.ts.map +1 -1
  69. package/lib/services/aiGen/aiGenFactory.service.d.ts.map +1 -1
  70. package/lib/services/aiGen/aiGenFactory.service.js +40 -0
  71. package/lib/services/aiGen/canonicalAdapters/cameraControl.types.d.ts +6 -3
  72. package/lib/services/aiGen/canonicalAdapters/cameraControl.types.d.ts.map +1 -1
  73. package/lib/services/aiGen/canonicalAdapters/cameraControl.types.js +35 -0
  74. package/lib/services/aiGen/canonicalAdapters/cameraDirection.d.ts +36 -0
  75. package/lib/services/aiGen/canonicalAdapters/cameraDirection.d.ts.map +1 -0
  76. package/lib/services/aiGen/canonicalAdapters/cameraDirection.js +168 -0
  77. package/lib/services/aiGen/canonicalAdapters/index.d.ts +1 -0
  78. package/lib/services/aiGen/canonicalAdapters/index.d.ts.map +1 -1
  79. package/lib/services/aiGen/canonicalAdapters/index.js +1 -0
  80. package/lib/services/aiGen/canonicalAdapters/multiShot.types.d.ts +3 -2
  81. package/lib/services/aiGen/canonicalAdapters/multiShot.types.d.ts.map +1 -1
  82. package/lib/services/aiGen/helpers.d.ts +40 -0
  83. package/lib/services/aiGen/helpers.d.ts.map +1 -1
  84. package/lib/services/aiGen/helpers.js +48 -2
  85. package/lib/services/aiGen/index.d.ts +1 -0
  86. package/lib/services/aiGen/index.d.ts.map +1 -1
  87. package/lib/services/aiGen/index.js +3 -0
  88. package/lib/services/aiGen/providers/alibaba/alibaba.d.ts +13 -1
  89. package/lib/services/aiGen/providers/alibaba/alibaba.d.ts.map +1 -1
  90. package/lib/services/aiGen/providers/alibaba/alibaba.js +313 -33
  91. package/lib/services/aiGen/providers/bytedance/bytedance.service.d.ts +29 -1
  92. package/lib/services/aiGen/providers/bytedance/bytedance.service.d.ts.map +1 -1
  93. package/lib/services/aiGen/providers/bytedance/bytedance.service.js +371 -54
  94. package/lib/services/aiGen/providers/google/google.service.d.ts +16 -0
  95. package/lib/services/aiGen/providers/google/google.service.d.ts.map +1 -1
  96. package/lib/services/aiGen/providers/google/google.service.js +372 -116
  97. package/lib/services/aiGen/providers/google/googleKeyPool.d.ts +6 -0
  98. package/lib/services/aiGen/providers/google/googleKeyPool.d.ts.map +1 -1
  99. package/lib/services/aiGen/providers/google/googleKeyPool.js +8 -0
  100. package/lib/services/aiGen/providers/kling/kling.service.d.ts +17 -1
  101. package/lib/services/aiGen/providers/kling/kling.service.d.ts.map +1 -1
  102. package/lib/services/aiGen/providers/kling/kling.service.js +59 -3
  103. package/lib/services/aiGen/providers/kling/klingCredits.d.ts +1 -1
  104. package/lib/services/aiGen/providers/kling/klingCredits.d.ts.map +1 -1
  105. package/lib/services/aiGen/providers/kling/klingCredits.js +19 -1
  106. package/lib/services/aiGen/providers/kling/klingRequests.d.ts +37 -7
  107. package/lib/services/aiGen/providers/kling/klingRequests.d.ts.map +1 -1
  108. package/lib/services/aiGen/providers/kling/klingRequests.js +191 -13
  109. package/lib/services/aiGen/providers/kling/types.d.ts +78 -0
  110. package/lib/services/aiGen/providers/kling/types.d.ts.map +1 -1
  111. package/lib/services/aiGen/providers/minimax/minimax.service.d.ts +11 -2
  112. package/lib/services/aiGen/providers/minimax/minimax.service.d.ts.map +1 -1
  113. package/lib/services/aiGen/providers/minimax/minimax.service.js +168 -2
  114. package/lib/services/aiGen/providers/minimax/types.d.ts +63 -0
  115. package/lib/services/aiGen/providers/minimax/types.d.ts.map +1 -1
  116. package/lib/services/aiGen/providers/pixverse/pixverse.service.d.ts +12 -0
  117. package/lib/services/aiGen/providers/pixverse/pixverse.service.d.ts.map +1 -1
  118. package/lib/services/aiGen/providers/pixverse/pixverse.service.js +131 -17
  119. package/lib/services/aiGen/providers/runway/hostedModels.d.ts +84 -0
  120. package/lib/services/aiGen/providers/runway/hostedModels.d.ts.map +1 -0
  121. package/lib/services/aiGen/providers/runway/hostedModels.js +266 -0
  122. package/lib/services/aiGen/providers/runway/index.d.ts +1 -0
  123. package/lib/services/aiGen/providers/runway/index.d.ts.map +1 -1
  124. package/lib/services/aiGen/providers/runway/index.js +1 -0
  125. package/lib/services/aiGen/providers/runway/runway.service.d.ts +1 -1
  126. package/lib/services/aiGen/providers/runway/runway.service.d.ts.map +1 -1
  127. package/lib/services/aiGen/providers/runway/runway.service.js +118 -21
  128. package/lib/services/aiGen/providers/runway/types.d.ts +18 -3
  129. package/lib/services/aiGen/providers/runway/types.d.ts.map +1 -1
  130. package/lib/services/aiGen/providers/runway/types.js +31 -3
  131. package/lib/services/aiGen/providers/types.d.ts +55 -0
  132. package/lib/services/aiGen/providers/types.d.ts.map +1 -1
  133. package/lib/services/aiGen/providers/xai/xai.service.d.ts +19 -0
  134. package/lib/services/aiGen/providers/xai/xai.service.d.ts.map +1 -0
  135. package/lib/services/aiGen/providers/xai/xai.service.js +205 -0
  136. package/lib/services/firestore.service.d.ts +4 -0
  137. package/lib/services/firestore.service.d.ts.map +1 -1
  138. package/lib/services/firestore.service.js +5 -0
  139. package/lib/services/index.d.ts +2 -0
  140. package/lib/services/index.d.ts.map +1 -1
  141. package/lib/services/index.js +2 -0
  142. package/lib/services/klingElements/klingElementLibrary.service.d.ts +37 -0
  143. package/lib/services/klingElements/klingElementLibrary.service.d.ts.map +1 -0
  144. package/lib/services/klingElements/klingElementLibrary.service.js +179 -0
  145. package/lib/services/trialGuard/index.d.ts +2 -0
  146. package/lib/services/trialGuard/index.d.ts.map +1 -0
  147. package/lib/services/trialGuard/index.js +17 -0
  148. package/lib/services/trialGuard/trialSignals.d.ts +88 -0
  149. package/lib/services/trialGuard/trialSignals.d.ts.map +1 -0
  150. package/lib/services/trialGuard/trialSignals.js +160 -0
  151. package/lib/utils/helpers.d.ts.map +1 -1
  152. package/lib/utils/helpers.js +5 -1
  153. package/package.json +2 -1
@@ -1,5 +1,6 @@
1
1
  import { BaseAiGenProviderService } from "../baseAiGenProvider.service";
2
2
  import { CreditUsageParams, VideoGenerationParams, VideoGenerationResult, VideoStatusParams, VideoStatusResult } from "../types";
3
+ import { KlingCreateElementRequest, KlingElementInfo, KlingElementTask } from "./types";
3
4
  /**
4
5
  * Kling runs TWO auth schemes. Verified against the live API 2026-07-22,
5
6
  * re-verified 2026-09-16.
@@ -50,6 +51,13 @@ export declare class KlingService extends BaseAiGenProviderService {
50
51
  * Polling likewise goes to checkTurboVideoStatus, never the v1 prober.
51
52
  */
52
53
  private generateTurboVideo;
54
+ /**
55
+ * kling-3.0-omni submit on API 2.0. Single endpoint for every input mix
56
+ * (t2v / first-last frame / reference images / feature video / base-video
57
+ * edit) — buildOmni2VideoBody decides the contents[]. Shares Turbo's
58
+ * envelope, auth and poller.
59
+ */
60
+ private generateOmni2Video;
53
61
  /**
54
62
  * Extend a previously-generated Kling video by ~4-5s. Takes the Kling task id
55
63
  * of the source video (must have been generated by this Kling account).
@@ -62,9 +70,17 @@ export declare class KlingService extends BaseAiGenProviderService {
62
70
  private generateAvatarVideo;
63
71
  private requestWithTimeoutRetry;
64
72
  checkVideoStatus(params: VideoStatusParams): Promise<VideoStatusResult>;
73
+ /** Submit an element-creation task. Returns Kling's task id. */
74
+ createElement(body: KlingCreateElementRequest): Promise<string>;
75
+ /** Poll one element-creation task. */
76
+ getElementTask(taskId: string): Promise<KlingElementTask>;
77
+ /** Kling's official preset elements (one page; ≤500 per page). */
78
+ listPresetElements(pageNum?: number, pageSize?: number): Promise<KlingElementInfo[]>;
79
+ /** Delete a custom element (presets can't be deleted). */
80
+ deleteElement(elementId: string): Promise<void>;
65
81
  /**
66
82
  * Pick the credential for the surface being called. The API 2.0 key is
67
- * optional in env — only kling-v3.0-turbo needs it — so its absence must not
83
+ * optional in env — only the API 2.0 models (turbo, 3.0-omni) need it — so its absence must not
68
84
  * break the JWT models that make up the rest of the catalog. Failing here
69
85
  * (rather than letting Kling return an opaque 401) means the scene fails at
70
86
  * SUBMIT with no task id, which our refund policy treats as never-billed →
@@ -1 +1 @@
1
- {"version":3,"file":"kling.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/kling/kling.service.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAyBlB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE7C;;;;;GAKG;AACH,qBAAa,YAAa,SAAQ,wBAAwB;IACxD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAW;IAC3C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IASxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkD;IAC9E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAmD;;YAWlE,OAAO;IAiCf,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IA+EjC;;;;;;;;OAQG;YACW,kBAAkB;IAgChC;;;;OAIG;YACW,WAAW;YA6BX,iBAAiB;YA6BjB,qBAAqB;YAgCrB,eAAe;YAkDf,mBAAmB;YAgCnB,uBAAuB;IAsI/B,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAiB7E;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;IAiBxB,cAAc,IAAI,MAAM;IAexB,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM;CAGjD"}
1
+ {"version":3,"file":"kling.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/kling/kling.service.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,gBAAgB,EAMjB,MAAM,SAAS,CAAC;AAoBjB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE7C;;;;;GAKG;AACH,qBAAa,YAAa,SAAQ,wBAAwB;IACxD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAW;IAC3C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IASxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkD;IAC9E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAmD;;YAWlE,OAAO;IAiCf,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IAmFjC;;;;;;;;OAQG;YACW,kBAAkB;IAgChC;;;;;OAKG;YACW,kBAAkB;IA4BhC;;;;OAIG;YACW,WAAW;YA6BX,iBAAiB;YA6BjB,qBAAqB;YAgCrB,eAAe;YAkDf,mBAAmB;YAgCnB,uBAAuB;IAsI/B,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAsB7E,gEAAgE;IAC1D,aAAa,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,MAAM,CAAC;IASrE,sCAAsC;IAChC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAQ/D,kEAAkE;IAC5D,kBAAkB,CAAC,OAAO,SAAI,EAAE,QAAQ,SAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAUlF,0DAA0D;IACpD,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASrD;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;IAiBxB,cAAc,IAAI,MAAM;IAexB,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM;CAGjD"}
@@ -102,6 +102,9 @@ class KlingService extends baseAiGenProvider_service_1.BaseAiGenProviderService
102
102
  if (params.modelKey === "kling-v3.0-turbo") {
103
103
  return this.generateTurboVideo(params);
104
104
  }
105
+ if (params.modelKey === "kling-v3.0-omni") {
106
+ return this.generateOmni2Video(params);
107
+ }
105
108
  const modelId = aiModels_1.aiModelConfigs[params.modelKey]?.modelId;
106
109
  if (!modelId)
107
110
  throw new Error(`Unknown modelKey: ${params.modelKey}`);
@@ -146,6 +149,28 @@ class KlingService extends baseAiGenProvider_service_1.BaseAiGenProviderService
146
149
  });
147
150
  return { task: task.data.id, status: types_1.EVideoSceneStatus.TRIGGERED };
148
151
  }
152
+ /**
153
+ * kling-3.0-omni submit on API 2.0. Single endpoint for every input mix
154
+ * (t2v / first-last frame / reference images / feature video / base-video
155
+ * edit) — buildOmni2VideoBody decides the contents[]. Shares Turbo's
156
+ * envelope, auth and poller.
157
+ */
158
+ async generateOmni2Video(params) {
159
+ const modelId = aiModels_1.aiModelConfigs[params.modelKey]?.modelId;
160
+ if (!modelId)
161
+ throw new Error(`Unknown modelKey: ${params.modelKey}`);
162
+ const body = (0, klingRequests_1.buildOmni2VideoBody)(params);
163
+ const starttime = Date.now();
164
+ const task = await this.requestWithTimeoutRetry(`/omni-video/${modelId}`, "POST", body, 4, this.generateTimeout, "apiKey");
165
+ logger_1.logger.info("Kling generateOmni2Video submitted", {
166
+ modelKey: params.modelKey,
167
+ modelId,
168
+ contentTypes: body.contents.map((c) => c.type),
169
+ taskId: task.data.id,
170
+ durationMs: Date.now() - starttime,
171
+ });
172
+ return { task: task.data.id, status: types_1.EVideoSceneStatus.TRIGGERED };
173
+ }
149
174
  /**
150
175
  * Extend a previously-generated Kling video by ~4-5s. Takes the Kling task id
151
176
  * of the source video (must have been generated by this Kling account).
@@ -368,14 +393,38 @@ class KlingService extends baseAiGenProvider_service_1.BaseAiGenProviderService
368
393
  // API 2.0 task — different endpoint, array response, and "succeeded" vs
369
394
  // v1's "succeed". The v1 prober would 404 down its whole endpoint list and
370
395
  // report the task missing.
371
- if (params.modelKey === "kling-v3.0-turbo") {
396
+ if (params.modelKey === "kling-v3.0-turbo" || params.modelKey === "kling-v3.0-omni") {
372
397
  return (0, klingStatus_1.checkTurboVideoStatus)(deps, params);
373
398
  }
374
399
  return (0, klingStatus_1.checkRegularVideoStatus)(deps, params);
375
400
  }
401
+ // ─── Element Library ──────────────────────────────────────────────────
402
+ // Same API key (and therefore the same Kling account) as kling-v3.0-omni,
403
+ // so element ids created here resolve in Omni generations. Ownership per
404
+ // end user is enforced one level up (KlingElementLibrary).
405
+ /** Submit an element-creation task. Returns Kling's task id. */
406
+ async createElement(body) {
407
+ const res = await this.request("/v1/general/advanced-custom-elements", "POST", body);
408
+ return unwrapKlingEnvelope(res, "create element").task_id;
409
+ }
410
+ /** Poll one element-creation task. */
411
+ async getElementTask(taskId) {
412
+ const res = await this.requestWithTimeoutRetry(`/v1/general/advanced-custom-elements/${encodeURIComponent(taskId)}`, "GET");
413
+ return unwrapKlingEnvelope(res, "query element");
414
+ }
415
+ /** Kling's official preset elements (one page; ≤500 per page). */
416
+ async listPresetElements(pageNum = 1, pageSize = 500) {
417
+ const res = await this.requestWithTimeoutRetry(`/v1/general/advanced-presets-elements?pageNum=${pageNum}&pageSize=${pageSize}`, "GET");
418
+ return unwrapKlingEnvelope(res, "list preset elements").flatMap((t) => t.task_result?.elements ?? []);
419
+ }
420
+ /** Delete a custom element (presets can't be deleted). */
421
+ async deleteElement(elementId) {
422
+ const res = await this.request("/v1/general/delete-advanced-elements", "POST", { element_id: elementId });
423
+ unwrapKlingEnvelope(res, "delete element");
424
+ }
376
425
  /**
377
426
  * Pick the credential for the surface being called. The API 2.0 key is
378
- * optional in env — only kling-v3.0-turbo needs it — so its absence must not
427
+ * optional in env — only the API 2.0 models (turbo, 3.0-omni) need it — so its absence must not
379
428
  * break the JWT models that make up the rest of the catalog. Failing here
380
429
  * (rather than letting Kling return an opaque 401) means the scene fails at
381
430
  * SUBMIT with no task id, which our refund policy treats as never-billed →
@@ -387,7 +436,7 @@ class KlingService extends baseAiGenProvider_service_1.BaseAiGenProviderService
387
436
  const apiKey = process.env.KLING_API_KEY;
388
437
  if (!apiKey) {
389
438
  // Operator detail goes to Loki/Slack; the user sees only the safe copy.
390
- logger_1.logger.error("KLING_API_KEY is not set — Kling API 2.0 models (kling-v3.0-turbo) need a console-issued API key from https://kling.ai/dev/api-key. The legacy AK/SK JWT is rejected by that surface with HTTP 401 code 1002.");
439
+ logger_1.logger.error("KLING_API_KEY is not set — Kling API 2.0 models (kling-v3.0-turbo, kling-v3.0-omni) need a console-issued API key from https://kling.ai/dev/api-key. The legacy AK/SK JWT is rejected by that surface with HTTP 401 code 1002.");
391
440
  throw new errors_1.UserFacingError("This model is temporarily unavailable. Please pick another model.", errors_1.USER_FACING_ERROR_CODES.PROVIDER_AUTH_ERROR);
392
441
  }
393
442
  return apiKey;
@@ -409,3 +458,10 @@ class KlingService extends baseAiGenProvider_service_1.BaseAiGenProviderService
409
458
  }
410
459
  }
411
460
  exports.KlingService = KlingService;
461
+ /** Kling answers HTTP 200 with a non-zero `code` for request-level errors. */
462
+ function unwrapKlingEnvelope(res, what) {
463
+ if (res.code !== 0) {
464
+ throw new errors_1.UserFacingError(`Kling couldn't ${what}: ${res.message || `code ${res.code}`}`, errors_1.USER_FACING_ERROR_CODES.CAPABILITY_MISMATCH);
465
+ }
466
+ return res.data;
467
+ }
@@ -5,5 +5,5 @@ import { CreditUsageParams } from "../types";
5
5
  * (per-second, 5s-rounded), v2.6 (audio/noAudio tier table), and the base
6
6
  * table with deferred I2V / generate_audio upcharges.
7
7
  */
8
- export declare function getKlingCreditUsed({ modelKey, mode, duration, multiClip, audio, inputType, }: CreditUsageParams): number;
8
+ export declare function getKlingCreditUsed({ modelKey, mode: requestedMode, duration, multiClip, audio, inputType, resolution, }: CreditUsageParams): number;
9
9
  //# sourceMappingURL=klingCredits.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"klingCredits.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/kling/klingCredits.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,IAA8B,EAC9B,QAAY,EACZ,SAAiB,EACjB,KAAa,EACb,SAAS,GACV,EAAE,iBAAiB,GAAG,MAAM,CAoE5B"}
1
+ {"version":3,"file":"klingCredits.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/kling/klingCredits.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG7C;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,IAAI,EAAE,aAAa,EACnB,QAAY,EACZ,SAAiB,EACjB,KAAa,EACb,SAAS,EACT,UAAU,GACX,EAAE,iBAAiB,GAAG,MAAM,CAuF5B"}
@@ -5,15 +5,20 @@ const aiModels_1 = require("../../../../globals/aiModels");
5
5
  const logger_1 = require("../../../../utils/logger");
6
6
  const helpers_1 = require("../../../../utils/helpers");
7
7
  const types_1 = require("../../types");
8
+ const klingRequests_1 = require("./klingRequests");
8
9
  /**
9
10
  * Kling credit calculation. Pure (config lookup + arithmetic) — broken out of
10
11
  * KlingService.getCreditUsed. Handles the three pricing shapes: avatar
11
12
  * (per-second, 5s-rounded), v2.6 (audio/noAudio tier table), and the base
12
13
  * table with deferred I2V / generate_audio upcharges.
13
14
  */
14
- function getKlingCreditUsed({ modelKey, mode = types_1.EVideoMode.PROFESSIONAL, duration = 5, multiClip = false, audio = false, inputType, }) {
15
+ function getKlingCreditUsed({ modelKey, mode: requestedMode, duration = 5, multiClip = false, audio = false, inputType, resolution, }) {
15
16
  const modelConfig = aiModels_1.aiModelConfigs[modelKey];
16
17
  const applyFloor = !multiClip;
18
+ // Legacy default for the table-priced models. kling-3.0-omni reads
19
+ // `requestedMode` instead: its request builder defaults to 720p, and
20
+ // billing an unset mode as pro would charge the 1080p rate for a 720p clip.
21
+ const mode = requestedMode ?? types_1.EVideoMode.PROFESSIONAL;
17
22
  // Avatar: per-second pricing based on mode. Kling lipsync bills in
18
23
  // 5-second increments (a 7s clip is billed as 10s).
19
24
  if (modelKey === "kling-avatar") {
@@ -35,6 +40,19 @@ function getKlingCreditUsed({ modelKey, mode = types_1.EVideoMode.PROFESSIONAL,
35
40
  ?? 0.112;
36
41
  return (0, helpers_1.getCreditsFromCost)(perSecond * duration, applyFloor);
37
42
  }
43
+ // kling-3.0-omni (API 2.0): per-second, three tiers by video input × native
44
+ // audio, keyed by the SAME resolution the request builder sends. Any video
45
+ // input wins over audio: Kling allows no native audio with a video attached.
46
+ if (modelKey === "kling-v3.0-omni") {
47
+ const res = (0, klingRequests_1.resolveKlingOmni2Resolution)(resolution, requestedMode);
48
+ const table = inputType === "video"
49
+ ? modelConfig?.cost?.videoInputPerSecondByResolution
50
+ : audio
51
+ ? modelConfig?.cost?.nativeAudioPerSecondByResolution
52
+ : modelConfig?.cost?.perSecondByResolution;
53
+ const perSecond = table?.[res] ?? 0.168;
54
+ return (0, helpers_1.getCreditsFromCost)(perSecond * duration, applyFloor);
55
+ }
38
56
  // v2.6 splits cost by audio/noAudio tier (audio is 2× upcharge).
39
57
  if (modelKey === "kling-v2.6") {
40
58
  const branch = audio ? modelConfig?.cost?.audio : modelConfig?.cost?.noAudio;
@@ -1,15 +1,19 @@
1
1
  import { VideoGenerationParams } from "../types";
2
- import { KlingAvatarGenerateRequest, KlingImageToVideoRequest, KlingLipSyncRequest, KlingMotionControlRequest, KlingOmniVideoRequest, KlingTurboImageToVideoRequest, KlingTurboTextToVideoRequest, KlingVideoGenerateRequest } from "./types";
2
+ import type { MultiShot } from "../../canonicalAdapters/multiShot.types";
3
+ import { KlingAvatarGenerateRequest, KlingImageToVideoRequest, KlingLipSyncRequest, KlingMotionControlRequest, KlingOmniVideoRequest, KlingOmni2Request, KlingOmni2Resolution, KlingTurboImageToVideoRequest, KlingTurboTextToVideoRequest, KlingVideoGenerateRequest } from "./types";
3
4
  /**
4
- * Pure request-body builders mapping our provider-agnostic
5
- * VideoGenerationParams onto Kling's per-endpoint request shapes. No I/O —
6
- * KlingService calls these, then submits the result. Keeping them here makes
7
- * the per-endpoint field wiring testable in isolation and the service class a
8
- * thin dispatcher.
5
+ * Canonical multiShot → Kling 3.0's prompt-encoded storyboard,
6
+ * "shot 1, 3, words; shot 2, 2, words;" (kling.ai/document-api/api/video/
7
+ * 3-0-omni/text-to-video and 3-0-turbo/*, fetched 2026-09-29). Each shot is
8
+ * ≥ 1s and the shot durations must sum to the video duration: caller-supplied
9
+ * durations are kept when they already satisfy that, otherwise the total is
10
+ * split evenly (remainder to the earliest shots). Semicolons inside a shot's
11
+ * text would read as a separator, so they become commas.
9
12
  */
13
+ export declare function toKlingShotPrompt(shots: MultiShot, totalDuration: number): string;
10
14
  /**
11
15
  * text2video / image2video body. Routes by the presence of inputImageUrl and
12
- * wires the shared optional fields (negative prompt, cfg, camera control,
16
+ * wires the shared optional fields (negative prompt, cfg, camera direction,
13
17
  * audio/sound tier) plus the i2v-only mask / tail-frame fields.
14
18
  */
15
19
  export declare function buildVideoGenerateRequest(params: VideoGenerationParams, modelId: string): KlingVideoGenerateRequest | KlingImageToVideoRequest;
@@ -42,4 +46,30 @@ export declare function buildLipSyncBody(params: VideoGenerationParams, sessionI
42
46
  * an agent-authored scene may carry extras from a prior model.
43
47
  */
44
48
  export declare function buildTurboVideoBody(params: VideoGenerationParams): KlingTurboTextToVideoRequest | KlingTurboImageToVideoRequest;
49
+ /**
50
+ * Output resolution for kling-3.0-omni. An explicit `resolution` wins (case-
51
+ * insensitive, so "4K" works); otherwise our canonical `mode` maps with
52
+ * Kling's own legacy equivalence (std=720p, pro=1080p, "4k"=4k). Shared with
53
+ * getKlingCreditUsed so the billed tier is always the requested tier.
54
+ */
55
+ export declare function resolveKlingOmni2Resolution(resolution: string | undefined, mode: string | undefined): KlingOmni2Resolution;
56
+ /**
57
+ * kling-3.0-omni body. Canonical params map onto contents[] as:
58
+ * inputImageUrl → first_frame
59
+ * lastFrameImageUrl → last_frame (only together with a first frame)
60
+ * referenceImageUrls → refer_image, ids image_1…image_n
61
+ * referenceVideoUrls → feature_video (style/motion reference), id video_1
62
+ * inputVideoUrl → base_video (the clip to EDIT), id video_1
63
+ * klingElements → element, ids element_1…element_n
64
+ * The prompt can cite those ids as @image_1 / @video_1 / @element_1.
65
+ *
66
+ * Audio: `audio: true` means native sound on a plain generation and "keep
67
+ * the original track" on a base-video edit. Kling allows no audio at all with
68
+ * a feature video, so there it is always "off".
69
+ *
70
+ * Kling's documented combination rules are enforced here so a bad mix fails
71
+ * at submit (no task id → full refund) with a readable message, instead of
72
+ * an opaque provider 400.
73
+ */
74
+ export declare function buildOmni2VideoBody(params: VideoGenerationParams): KlingOmni2Request;
45
75
  //# sourceMappingURL=klingRequests.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"klingRequests.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/kling/klingRequests.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEjD,OAAO,EAEL,0BAA0B,EAE1B,wBAAwB,EACxB,mBAAmB,EAEnB,yBAAyB,EACzB,qBAAqB,EAErB,6BAA6B,EAI7B,4BAA4B,EAC5B,yBAAyB,EAC1B,MAAM,SAAS,CAAC;AAEjB;;;;;;GAMG;AAEH;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,MAAM,GACd,yBAAyB,GAAG,wBAAwB,CAmDtD;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAC7B,MAAM,EAAE,qBAAqB,GAC5B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQzB;AAED,gFAAgF;AAChF,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,MAAM,GACd,qBAAqB,CA8CvB;AAED,sEAAsE;AACtE,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,MAAM,GACd,yBAAyB,CAW3B;AAED,iDAAiD;AACjD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,qBAAqB,GAC5B,0BAA0B,CAS5B;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,qBAAqB,EAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC5C,mBAAmB,CAgBrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,qBAAqB,GAC5B,4BAA4B,GAAG,6BAA6B,CA+B9D"}
1
+ {"version":3,"file":"klingRequests.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/kling/klingRequests.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,OAAO,EAEL,0BAA0B,EAE1B,wBAAwB,EACxB,mBAAmB,EAEnB,yBAAyB,EACzB,qBAAqB,EAGrB,iBAAiB,EACjB,oBAAoB,EAGpB,6BAA6B,EAI7B,4BAA4B,EAC5B,yBAAyB,EAC1B,MAAM,SAAS,CAAC;AAcjB;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAgBjF;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,MAAM,GACd,yBAAyB,GAAG,wBAAwB,CA+DtD;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAC7B,MAAM,EAAE,qBAAqB,GAC5B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQzB;AAED,gFAAgF;AAChF,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,MAAM,GACd,qBAAqB,CA+CvB;AAED,sEAAsE;AACtE,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,MAAM,GACd,yBAAyB,CAW3B;AAED,iDAAiD;AACjD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,qBAAqB,GAC5B,0BAA0B,CAS5B;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,qBAAqB,EAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC5C,mBAAmB,CAgBrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,qBAAqB,GAC5B,4BAA4B,GAAG,6BAA6B,CAoC9D;AAID;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,IAAI,EAAE,MAAM,GAAG,SAAS,GACvB,oBAAoB,CAKtB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,qBAAqB,GAAG,iBAAiB,CAkGpF"}
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toKlingShotPrompt = toKlingShotPrompt;
3
4
  exports.buildVideoGenerateRequest = buildVideoGenerateRequest;
4
5
  exports.buildExtendBody = buildExtendBody;
5
6
  exports.buildOmniVideoBody = buildOmniVideoBody;
@@ -7,8 +8,11 @@ exports.buildMotionControlBody = buildMotionControlBody;
7
8
  exports.buildAvatarRequest = buildAvatarRequest;
8
9
  exports.buildLipSyncBody = buildLipSyncBody;
9
10
  exports.buildTurboVideoBody = buildTurboVideoBody;
11
+ exports.resolveKlingOmni2Resolution = resolveKlingOmni2Resolution;
12
+ exports.buildOmni2VideoBody = buildOmni2VideoBody;
10
13
  const types_1 = require("../../types");
11
- const cameraAdapter_1 = require("./cameraAdapter");
14
+ const cameraDirection_1 = require("../../canonicalAdapters/cameraDirection");
15
+ const errors_1 = require("../../../../utils/errors");
12
16
  /**
13
17
  * Pure request-body builders mapping our provider-agnostic
14
18
  * VideoGenerationParams onto Kling's per-endpoint request shapes. No I/O —
@@ -16,12 +20,46 @@ const cameraAdapter_1 = require("./cameraAdapter");
16
20
  * the per-endpoint field wiring testable in isolation and the service class a
17
21
  * thin dispatcher.
18
22
  */
23
+ /** Kling 3.0 / 3.0 Turbo prompt-encoded multi-shot limits (docs, 2026-09-29). */
24
+ const KLING_MAX_SHOTS = 6;
25
+ const KLING_MAX_SHOT_CHARS = 512;
26
+ /**
27
+ * Canonical multiShot → Kling 3.0's prompt-encoded storyboard,
28
+ * "shot 1, 3, words; shot 2, 2, words;" (kling.ai/document-api/api/video/
29
+ * 3-0-omni/text-to-video and 3-0-turbo/*, fetched 2026-09-29). Each shot is
30
+ * ≥ 1s and the shot durations must sum to the video duration: caller-supplied
31
+ * durations are kept when they already satisfy that, otherwise the total is
32
+ * split evenly (remainder to the earliest shots). Semicolons inside a shot's
33
+ * text would read as a separator, so they become commas.
34
+ */
35
+ function toKlingShotPrompt(shots, totalDuration) {
36
+ const count = Math.max(1, Math.min(shots.length, KLING_MAX_SHOTS, totalDuration));
37
+ const used = shots.slice(0, count);
38
+ const given = used.map((s) => s.duration);
39
+ const keepGiven = given.every((d) => d !== undefined && Number.isInteger(d) && d >= 1) &&
40
+ given.reduce((a, b) => a + b, 0) === totalDuration;
41
+ const base = Math.floor(totalDuration / count);
42
+ const remainder = totalDuration % count;
43
+ return used
44
+ .map((s, i) => {
45
+ const seconds = keepGiven ? given[i] : base + (i < remainder ? 1 : 0);
46
+ const words = s.prompt.replace(/;/g, ",").trim().slice(0, KLING_MAX_SHOT_CHARS);
47
+ return `shot ${i + 1}, ${seconds}, ${words};`;
48
+ })
49
+ .join(" ");
50
+ }
19
51
  /**
20
52
  * text2video / image2video body. Routes by the presence of inputImageUrl and
21
- * wires the shared optional fields (negative prompt, cfg, camera control,
53
+ * wires the shared optional fields (negative prompt, cfg, camera direction,
22
54
  * audio/sound tier) plus the i2v-only mask / tail-frame fields.
23
55
  */
24
56
  function buildVideoGenerateRequest(params, modelId) {
57
+ params = (0, cameraDirection_1.applyCameraDirection)(params);
58
+ // Kling 3.0 reads multi-shot from the prompt (no multi_prompt[] on this
59
+ // endpoint) — before this, a v3.0 multiShot request was silently dropped.
60
+ if (params.multiShot?.length && params.modelKey === "kling-v3.0") {
61
+ params = { ...params, prompt: toKlingShotPrompt(params.multiShot, params.duration ?? 5) };
62
+ }
25
63
  // Common optional fields shared by text2video and image2video endpoints.
26
64
  const optional = {};
27
65
  if (params.negativePrompt)
@@ -32,20 +70,24 @@ function buildVideoGenerateRequest(params, modelId) {
32
70
  optional.callback_url = params.callbackUrl;
33
71
  if (params.externalTaskId)
34
72
  optional.external_task_id = params.externalTaskId;
35
- if (params.cameraControl) {
36
- const cc = (0, cameraAdapter_1.toKlingCameraControl)(params.cameraControl);
37
- if (cc)
38
- optional.camera_control = cc;
39
- }
40
- // v2.6 uses `sound: "on"|"off"` as a pricing-tier toggle. v3 uses
41
- // `generate_audio: boolean` for native audio synthesis. Route by model.
73
+ // Kling's current text2video / image2video docs (2.5-turbo, 2.6, v3 —
74
+ // kling.ai/document-api/api/video/2-6/*, fetched 2026-09-29) no longer list
75
+ // `camera_control`; camera moves go in the prompt. applyCameraDirection
76
+ // (top of this function) does that.
77
+ // REMOVED FOR v2 — kept for reference:
78
+ // if (params.cameraControl) {
79
+ // const cc = toKlingCameraControl(params.cameraControl);
80
+ // if (cc) optional.camera_control = cc;
81
+ // }
82
+ // Native audio is `sound: "on"|"off"` on every model that has it (2.6 and
83
+ // v3 per the capability map; 2.5-turbo has none). The docs have no
84
+ // `generate_audio` field — sending it for v3 left audio off.
42
85
  if (params.audio !== undefined) {
43
- if (params.modelKey === "kling-v3.0") {
44
- optional.generate_audio = Boolean(params.audio);
45
- }
46
- else if (params.modelKey === "kling-v2.6") {
86
+ if (params.modelKey === "kling-v3.0" || params.modelKey === "kling-v2.6") {
47
87
  optional.sound = params.audio ? "on" : "off";
48
88
  }
89
+ // REMOVED FOR v2 — kept for reference: the undocumented v3 flag.
90
+ // if (params.modelKey === "kling-v3.0") optional.generate_audio = Boolean(params.audio);
49
91
  }
50
92
  const isImageToVideo = !!params.inputImageUrl;
51
93
  if (isImageToVideo) {
@@ -97,6 +139,7 @@ function buildExtendBody(params) {
97
139
  }
98
140
  /** OmniVideo body: start/end/reference frames, reference videos, multi-shot. */
99
141
  function buildOmniVideoBody(params, modelId) {
142
+ params = (0, cameraDirection_1.applyCameraDirection)(params);
100
143
  const body = {
101
144
  model_name: modelId,
102
145
  mode: params.mode || types_1.EVideoMode.STANDARD,
@@ -225,6 +268,10 @@ function buildTurboVideoBody(params) {
225
268
  options.watermark_info = { enabled: Boolean(params.watermark) };
226
269
  }
227
270
  const maybeOptions = Object.keys(options).length ? { options } : {};
271
+ // Turbo multi-shot is the same prompt-encoded storyboard as 3.0.
272
+ if (params.multiShot?.length) {
273
+ params = { ...params, prompt: toKlingShotPrompt(params.multiShot, settings.duration ?? 5) };
274
+ }
228
275
  if (params.inputImageUrl) {
229
276
  // I2V: prompt and image BOTH ride inside contents[].
230
277
  const contents = [];
@@ -236,3 +283,134 @@ function buildTurboVideoBody(params) {
236
283
  // T2V: prompt is a top-level string on this endpoint (not contents[]).
237
284
  return { prompt: params.prompt, settings, ...maybeOptions };
238
285
  }
286
+ // ─── Kling 3.0 Omni, API 2.0 (POST /omni-video/kling-3.0-omni) ──────────────
287
+ /**
288
+ * Output resolution for kling-3.0-omni. An explicit `resolution` wins (case-
289
+ * insensitive, so "4K" works); otherwise our canonical `mode` maps with
290
+ * Kling's own legacy equivalence (std=720p, pro=1080p, "4k"=4k). Shared with
291
+ * getKlingCreditUsed so the billed tier is always the requested tier.
292
+ */
293
+ function resolveKlingOmni2Resolution(resolution, mode) {
294
+ const r = resolution?.toLowerCase();
295
+ if (r === "720p" || r === "1080p" || r === "4k")
296
+ return r;
297
+ if (mode === "4k")
298
+ return "4k";
299
+ return mode === types_1.EVideoMode.PROFESSIONAL ? "1080p" : "720p";
300
+ }
301
+ /**
302
+ * kling-3.0-omni body. Canonical params map onto contents[] as:
303
+ * inputImageUrl → first_frame
304
+ * lastFrameImageUrl → last_frame (only together with a first frame)
305
+ * referenceImageUrls → refer_image, ids image_1…image_n
306
+ * referenceVideoUrls → feature_video (style/motion reference), id video_1
307
+ * inputVideoUrl → base_video (the clip to EDIT), id video_1
308
+ * klingElements → element, ids element_1…element_n
309
+ * The prompt can cite those ids as @image_1 / @video_1 / @element_1.
310
+ *
311
+ * Audio: `audio: true` means native sound on a plain generation and "keep
312
+ * the original track" on a base-video edit. Kling allows no audio at all with
313
+ * a feature video, so there it is always "off".
314
+ *
315
+ * Kling's documented combination rules are enforced here so a bad mix fails
316
+ * at submit (no task id → full refund) with a readable message, instead of
317
+ * an opaque provider 400.
318
+ */
319
+ function buildOmni2VideoBody(params) {
320
+ const modelId = "kling-3.0-omni";
321
+ const refImages = params.referenceImageUrls ?? [];
322
+ const refVideos = params.referenceVideoUrls ?? [];
323
+ const baseVideo = params.inputVideoUrl;
324
+ const hasVideo = !!baseVideo || refVideos.length > 0;
325
+ const fail = (msg) => {
326
+ throw new errors_1.UserFacingError(`${modelId}: ${msg}`, errors_1.USER_FACING_ERROR_CODES.CAPABILITY_MISMATCH);
327
+ };
328
+ if (params.lastFrameImageUrl && !params.inputImageUrl) {
329
+ fail("a last frame needs a first frame too.");
330
+ }
331
+ if (refVideos.length + (baseVideo ? 1 : 0) > 1) {
332
+ fail("takes at most one video (a reference video or a video to edit, not both).");
333
+ }
334
+ // REMOVED FOR v2 — kept for reference: image-only cap, before elements.
335
+ // const maxImages = hasVideo ? 4 : 7;
336
+ // if (refImages.length > maxImages) {
337
+ // fail(`takes at most ${maxImages} reference images${hasVideo ? " alongside a video" : ""} (got ${refImages.length}).`);
338
+ // }
339
+ // Element Library: multi-image elements share the reference-image budget;
340
+ // video-character elements have their own caps (Kling docs, 2026-09-29).
341
+ const elements = params.klingElements ?? [];
342
+ const imageElements = elements.filter((e) => e.referenceType === "image_refer").length;
343
+ const videoElements = elements.length - imageElements;
344
+ if (params.inputImageUrl && elements.length > 3) {
345
+ fail(`takes at most 3 elements with a first frame (got ${elements.length}).`);
346
+ }
347
+ if (hasVideo && videoElements > 0 && (imageElements > 0 || refImages.length > 0)) {
348
+ fail("with a video, a video-character element can't be combined with image elements or reference images.");
349
+ }
350
+ const maxVideoElements = hasVideo ? 1 : 3;
351
+ if (videoElements > maxVideoElements) {
352
+ fail(`takes at most ${maxVideoElements} video-character element${maxVideoElements > 1 ? "s" : ""}${hasVideo ? " alongside a video" : ""} (got ${videoElements}).`);
353
+ }
354
+ const maxImages = hasVideo || videoElements > 0 ? 4 : 7;
355
+ if (refImages.length + imageElements > maxImages) {
356
+ const what = imageElements ? "reference images + image elements" : "reference images";
357
+ const why = hasVideo ? " alongside a video" : videoElements > 0 ? " alongside a video-character element" : "";
358
+ fail(`takes at most ${maxImages} ${what}${why} (got ${refImages.length + imageElements}).`);
359
+ }
360
+ if (baseVideo && (params.inputImageUrl || params.lastFrameImageUrl)) {
361
+ fail("a video edit cannot also set a first or last frame.");
362
+ }
363
+ if (baseVideo && params.multiShot?.length) {
364
+ fail("a video edit cannot be multi-shot.");
365
+ }
366
+ const duration = params.duration ?? 5;
367
+ let prompt = params.prompt;
368
+ if (params.multiShot?.length)
369
+ prompt = toKlingShotPrompt(params.multiShot, duration);
370
+ if (!prompt)
371
+ fail("a prompt is required.");
372
+ if (prompt.length > 3072) {
373
+ throw new errors_1.UserFacingError(`${modelId} prompts are limited to 3072 characters (got ${prompt.length}).`, errors_1.USER_FACING_ERROR_CODES.PROMPT_TOO_LONG);
374
+ }
375
+ const contents = [{ type: "prompt", text: prompt }];
376
+ if (params.inputImageUrl)
377
+ contents.push({ type: "first_frame", url: params.inputImageUrl });
378
+ if (params.lastFrameImageUrl)
379
+ contents.push({ type: "last_frame", url: params.lastFrameImageUrl });
380
+ refImages.forEach((url, i) => contents.push({ type: "refer_image", url, id: `image_${i + 1}` }));
381
+ if (refVideos[0])
382
+ contents.push({ type: "feature_video", url: refVideos[0], id: "video_1" });
383
+ if (baseVideo)
384
+ contents.push({ type: "base_video", url: baseVideo, id: "video_1" });
385
+ elements.forEach((e, i) => contents.push({ type: "element", element_id: e.elementId, id: `element_${i + 1}` }));
386
+ // A feature (reference) video allows audio "off" only; a base-video edit
387
+ // allows "original" or "off"; native sound needs no video at all.
388
+ const audio = !params.audio || refVideos.length > 0
389
+ ? "off"
390
+ : baseVideo ? "original" : "native";
391
+ const settings = {
392
+ resolution: resolveKlingOmni2Resolution(params.resolution, params.mode),
393
+ duration,
394
+ audio,
395
+ // Kling defaults multi_shot to TRUE, which lets it cut a single-prompt
396
+ // clip into shots on its own. Send it explicitly, on only when the caller
397
+ // asked for shots (base-video edits were rejected above for that).
398
+ multi_shot: !!params.multiShot?.length,
399
+ };
400
+ if (params.aspectRatio) {
401
+ settings.aspect_ratio = params.aspectRatio;
402
+ }
403
+ else if (!params.inputImageUrl && refVideos.length === 0) {
404
+ // Required by Kling when nothing else fixes the frame shape.
405
+ settings.aspect_ratio = "16:9";
406
+ }
407
+ const options = {};
408
+ if (params.callbackUrl)
409
+ options.callback_url = params.callbackUrl;
410
+ if (params.externalTaskId)
411
+ options.external_task_id = params.externalTaskId;
412
+ if (params.watermark !== undefined) {
413
+ options.watermark_info = { enabled: Boolean(params.watermark) };
414
+ }
415
+ return Object.keys(options).length ? { contents, settings, options } : { contents, settings };
416
+ }
@@ -259,4 +259,82 @@ export interface KlingTurboTasksResponse {
259
259
  request_id: string;
260
260
  data: KlingTurboTask[];
261
261
  }
262
+ export type KlingOmni2Resolution = "720p" | "1080p" | "4k";
263
+ /** settings.audio — "original" keeps the reference/base video's own track. */
264
+ export type KlingOmni2Audio = "native" | "original" | "off";
265
+ /**
266
+ * contents[] entry. `id` is the handle the prompt cites (`@image_1`,
267
+ * `@video_1`) and must be unique within a task. `element` entries carry an
268
+ * `element_id` from Kling's Element Library instead of a url.
269
+ */
270
+ export interface KlingOmni2Content {
271
+ type: "prompt" | "first_frame" | "last_frame" | "refer_image" | "feature_video" | "base_video" | "element";
272
+ /** Set when type === "prompt". Max 3072 chars. */
273
+ text?: string;
274
+ url?: string;
275
+ element_id?: string;
276
+ id?: string;
277
+ }
278
+ export interface KlingOmni2Settings {
279
+ /** Default true on Kling's side; forced true with a feature_video. */
280
+ multi_shot?: boolean;
281
+ audio?: KlingOmni2Audio;
282
+ resolution?: KlingOmni2Resolution;
283
+ /** Required when there is no first frame and no reference video. */
284
+ aspect_ratio?: KlingAspectRatio;
285
+ /** 3–15s inclusive. */
286
+ duration?: number;
287
+ }
288
+ export interface KlingOmni2Request {
289
+ contents: KlingOmni2Content[];
290
+ settings?: KlingOmni2Settings;
291
+ options?: KlingTurboOptions;
292
+ }
293
+ export interface KlingCreateElementRequest {
294
+ element_name: string;
295
+ element_description: string;
296
+ reference_type: "image_refer" | "video_refer";
297
+ /** Required for image_refer: 1 frontal + 1–3 other angles / close-ups. */
298
+ element_image_list?: {
299
+ frontal_image: string;
300
+ refer_images: {
301
+ image_url: string;
302
+ }[];
303
+ };
304
+ /** Required for video_refer: one .mp4/.mov, 3–8s, 1080p, 16:9 or 9:16, ≤200MB. */
305
+ element_video_list?: {
306
+ refer_videos: {
307
+ video_url: string;
308
+ }[];
309
+ };
310
+ element_voice_id?: string;
311
+ tag_list?: {
312
+ tag_id: string;
313
+ }[];
314
+ callback_url?: string;
315
+ external_task_id?: string;
316
+ }
317
+ export interface KlingElementInfo {
318
+ element_id: number | string;
319
+ element_name: string;
320
+ element_description: string;
321
+ reference_type: "image_refer" | "video_refer";
322
+ owned_by?: string;
323
+ status?: "succeed" | "deleted";
324
+ }
325
+ export interface KlingElementTask {
326
+ task_id: string;
327
+ task_status: "submitted" | "processing" | "succeed" | "failed";
328
+ task_status_msg?: string;
329
+ task_result?: {
330
+ elements?: KlingElementInfo[];
331
+ };
332
+ final_unit_deduction?: string;
333
+ }
334
+ export interface KlingEnvelope<T> {
335
+ code: number;
336
+ message: string;
337
+ request_id?: string;
338
+ data: T;
339
+ }
262
340
  //# sourceMappingURL=types.d.ts.map