@use-lattice/litmus 0.121.3

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 (199) hide show
  1. package/LICENSE +19 -0
  2. package/dist/src/accounts-Bt1oJb1Z.cjs +219 -0
  3. package/dist/src/accounts-DjOU8Rm3.js +178 -0
  4. package/dist/src/agentic-utils-D03IiXQc.js +153 -0
  5. package/dist/src/agentic-utils-Dh7xaMQM.cjs +180 -0
  6. package/dist/src/agents-C6BIMlZa.js +231 -0
  7. package/dist/src/agents-DvIpNX1L.cjs +666 -0
  8. package/dist/src/agents-ZP0RP9vV.cjs +231 -0
  9. package/dist/src/agents-maJXdjbR.js +665 -0
  10. package/dist/src/aimlapi-BTbQjG2E.cjs +30 -0
  11. package/dist/src/aimlapi-CwMxqfXP.js +30 -0
  12. package/dist/src/audio-BBUdvsde.cjs +97 -0
  13. package/dist/src/audio-D5DPZ7I-.js +97 -0
  14. package/dist/src/base-BEysXrkq.cjs +222 -0
  15. package/dist/src/base-C451JQfq.js +193 -0
  16. package/dist/src/blobs-BY8MDmpo.js +230 -0
  17. package/dist/src/blobs-BgcNn97m.cjs +256 -0
  18. package/dist/src/cache-BBE_lsTA.cjs +4 -0
  19. package/dist/src/cache-BkrqU5Ba.js +237 -0
  20. package/dist/src/cache-DsCxFlsZ.cjs +297 -0
  21. package/dist/src/chat-CPJWDP6a.cjs +289 -0
  22. package/dist/src/chat-CXX3xzkk.cjs +811 -0
  23. package/dist/src/chat-CcDgZFJ4.js +787 -0
  24. package/dist/src/chat-Dz5ZeGO2.js +289 -0
  25. package/dist/src/chatkit-Dw0mKkML.cjs +1158 -0
  26. package/dist/src/chatkit-swAIVuea.js +1157 -0
  27. package/dist/src/chunk-DEq-mXcV.js +15 -0
  28. package/dist/src/claude-agent-sdk-BXZJtOg6.js +379 -0
  29. package/dist/src/claude-agent-sdk-CkfyjDoG.cjs +383 -0
  30. package/dist/src/cloudflare-ai-BzpJcqUH.js +161 -0
  31. package/dist/src/cloudflare-ai-Cmy_R1y2.cjs +161 -0
  32. package/dist/src/cloudflare-gateway-B9tVQKok.cjs +272 -0
  33. package/dist/src/cloudflare-gateway-DrD3ew3H.js +272 -0
  34. package/dist/src/codex-sdk-Dezj9Nwm.js +1056 -0
  35. package/dist/src/codex-sdk-Dl9D4k5B.cjs +1060 -0
  36. package/dist/src/cometapi-C-9YvCHC.js +54 -0
  37. package/dist/src/cometapi-DHgDKoO2.cjs +54 -0
  38. package/dist/src/completion-B8Ctyxpr.js +120 -0
  39. package/dist/src/completion-Cxrt08sj.cjs +131 -0
  40. package/dist/src/createHash-BwgE13yv.cjs +27 -0
  41. package/dist/src/createHash-DmPQkvBh.js +15 -0
  42. package/dist/src/docker-BiqcTwLv.js +80 -0
  43. package/dist/src/docker-C7tEJnP-.cjs +80 -0
  44. package/dist/src/esm-C62Zofr1.cjs +409 -0
  45. package/dist/src/esm-DMVc93eh.js +379 -0
  46. package/dist/src/evalResult-C3NJPQOo.cjs +301 -0
  47. package/dist/src/evalResult-C7JJAPBb.js +295 -0
  48. package/dist/src/evalResult-DoVTZZWI.cjs +2 -0
  49. package/dist/src/extractor-DnMD3fwt.cjs +391 -0
  50. package/dist/src/extractor-DtlL28vL.js +374 -0
  51. package/dist/src/fetch-BTxakTSg.cjs +1133 -0
  52. package/dist/src/fetch-DQckpUFz.js +928 -0
  53. package/dist/src/fileExtensions-DnqA1y9x.js +85 -0
  54. package/dist/src/fileExtensions-bYh77CN8.cjs +114 -0
  55. package/dist/src/genaiTracer-CyZrmaK0.cjs +268 -0
  56. package/dist/src/genaiTracer-D3fD9dNV.js +256 -0
  57. package/dist/src/graders-BNscxFrU.js +13644 -0
  58. package/dist/src/graders-D2oE9Msq.js +2 -0
  59. package/dist/src/graders-c0Ez_w-9.cjs +2 -0
  60. package/dist/src/graders-d0F2M3e9.cjs +14056 -0
  61. package/dist/src/image-0ZhE0VlR.cjs +280 -0
  62. package/dist/src/image-CWE1pdNv.js +257 -0
  63. package/dist/src/image-D9ZK6hwL.js +163 -0
  64. package/dist/src/image-DKZgZITg.cjs +163 -0
  65. package/dist/src/index.cjs +11366 -0
  66. package/dist/src/index.d.cts +19640 -0
  67. package/dist/src/index.d.ts +19641 -0
  68. package/dist/src/index.js +11306 -0
  69. package/dist/src/invariant-Ddh24eXh.js +25 -0
  70. package/dist/src/invariant-kfQ8Bu82.cjs +30 -0
  71. package/dist/src/knowledgeBase-BgPyGFUd.cjs +122 -0
  72. package/dist/src/knowledgeBase-DyHilYaP.js +122 -0
  73. package/dist/src/litellm-CyMeneHS.js +135 -0
  74. package/dist/src/litellm-DWDF73yF.cjs +135 -0
  75. package/dist/src/logger-C40ZGil9.js +717 -0
  76. package/dist/src/logger-DyfK9PBt.cjs +917 -0
  77. package/dist/src/luma-ray-BAU9X_ep.cjs +315 -0
  78. package/dist/src/luma-ray-nwVseBbv.js +313 -0
  79. package/dist/src/messages-B5ADWTTv.js +245 -0
  80. package/dist/src/messages-BCnZfqrS.cjs +257 -0
  81. package/dist/src/meteor-DLZZ3osF.cjs +134 -0
  82. package/dist/src/meteor-DUiCJRC-.js +134 -0
  83. package/dist/src/modelslab-00cveB8L.cjs +163 -0
  84. package/dist/src/modelslab-D9sCU_L7.js +163 -0
  85. package/dist/src/nova-reel-CTapvqYH.js +276 -0
  86. package/dist/src/nova-reel-DlWuuroF.cjs +278 -0
  87. package/dist/src/nova-sonic-5UPWfeMv.cjs +363 -0
  88. package/dist/src/nova-sonic-BhSwQNym.js +363 -0
  89. package/dist/src/openai-BWrJK9d8.cjs +52 -0
  90. package/dist/src/openai-DumO8WQn.js +47 -0
  91. package/dist/src/openclaw-B8brrjC_.cjs +577 -0
  92. package/dist/src/openclaw-Bkayww9q.js +571 -0
  93. package/dist/src/opencode-sdk-7xjoDNiM.cjs +562 -0
  94. package/dist/src/opencode-sdk-SGwAPxht.js +558 -0
  95. package/dist/src/otlpReceiver-CoAHfAN9.cjs +15 -0
  96. package/dist/src/otlpReceiver-oO3EQwI9.js +14 -0
  97. package/dist/src/providerRegistry-4yjhaEM8.js +45 -0
  98. package/dist/src/providerRegistry-DhV4rJIc.cjs +50 -0
  99. package/dist/src/providers-B5RJVG-7.cjs +33609 -0
  100. package/dist/src/providers-BdmZCLzV.js +33262 -0
  101. package/dist/src/providers-CxtRxn8e.js +2 -0
  102. package/dist/src/providers-DnQLNbx1.cjs +3 -0
  103. package/dist/src/pythonUtils-BD0druiM.cjs +275 -0
  104. package/dist/src/pythonUtils-IBhn5YGR.js +249 -0
  105. package/dist/src/quiverai-BDOwZBsM.cjs +213 -0
  106. package/dist/src/quiverai-D3JTF5lD.js +213 -0
  107. package/dist/src/responses-B2LCDCXZ.js +667 -0
  108. package/dist/src/responses-BvNm4Xv9.cjs +685 -0
  109. package/dist/src/rubyUtils-B0NwnfpY.cjs +245 -0
  110. package/dist/src/rubyUtils-BroxzZ7c.cjs +2 -0
  111. package/dist/src/rubyUtils-hqVw5UvJ.js +222 -0
  112. package/dist/src/sagemaker-Cno2V-Sx.js +689 -0
  113. package/dist/src/sagemaker-fV_KUgs5.cjs +691 -0
  114. package/dist/src/server-BOuAXb06.cjs +238 -0
  115. package/dist/src/server-CtI-EWzm.cjs +2 -0
  116. package/dist/src/server-Cy3DZymt.js +189 -0
  117. package/dist/src/slack-CP8xBePa.js +135 -0
  118. package/dist/src/slack-DSQ1yXVb.cjs +135 -0
  119. package/dist/src/store-BwDDaBjb.cjs +246 -0
  120. package/dist/src/store-DcbLC593.cjs +2 -0
  121. package/dist/src/store-IGpqMIkv.js +240 -0
  122. package/dist/src/tables-3Q2cL7So.cjs +373 -0
  123. package/dist/src/tables-Bi2fjr4W.js +288 -0
  124. package/dist/src/telemetry-Bg2WqF79.js +161 -0
  125. package/dist/src/telemetry-D0x6u5kX.cjs +166 -0
  126. package/dist/src/telemetry-DXNimrI0.cjs +2 -0
  127. package/dist/src/text-B_UCRPp2.js +22 -0
  128. package/dist/src/text-CW1cyrwj.cjs +33 -0
  129. package/dist/src/tokenUsageUtils-NYT-WKS6.js +138 -0
  130. package/dist/src/tokenUsageUtils-bVa1ga6f.cjs +173 -0
  131. package/dist/src/transcription-Cl_W16Pr.js +122 -0
  132. package/dist/src/transcription-yt1EecY8.cjs +124 -0
  133. package/dist/src/transform-BCtGrl_W.cjs +228 -0
  134. package/dist/src/transform-Bv6gG2MJ.cjs +1688 -0
  135. package/dist/src/transform-CY1wbpRy.js +1507 -0
  136. package/dist/src/transform-DU8rUL9P.cjs +2 -0
  137. package/dist/src/transform-yWaShiKr.js +216 -0
  138. package/dist/src/transformersAvailability-BGkzavwb.js +35 -0
  139. package/dist/src/transformersAvailability-DKoRtQLy.cjs +35 -0
  140. package/dist/src/types-5aqHpBwE.cjs +3769 -0
  141. package/dist/src/types-Bn6D9c4U.js +3300 -0
  142. package/dist/src/util-BkKlTkI2.js +293 -0
  143. package/dist/src/util-CTh0bfOm.cjs +1119 -0
  144. package/dist/src/util-D17oBwo7.cjs +328 -0
  145. package/dist/src/util-DsS_-v4p.js +613 -0
  146. package/dist/src/util-DuntT1Ga.js +951 -0
  147. package/dist/src/util-aWjdCYMI.cjs +667 -0
  148. package/dist/src/utils-CisQwpjA.js +94 -0
  149. package/dist/src/utils-yWamDvmz.cjs +123 -0
  150. package/dist/tsconfig.tsbuildinfo +1 -0
  151. package/drizzle/0000_lush_hellion.sql +36 -0
  152. package/drizzle/0001_wide_calypso.sql +3 -0
  153. package/drizzle/0002_tidy_juggernaut.sql +1 -0
  154. package/drizzle/0003_lively_naoko.sql +8 -0
  155. package/drizzle/0004_minor_peter_quill.sql +19 -0
  156. package/drizzle/0005_silky_millenium_guard.sql +2 -0
  157. package/drizzle/0006_harsh_caretaker.sql +42 -0
  158. package/drizzle/0007_cloudy_wong.sql +1 -0
  159. package/drizzle/0008_broad_boomer.sql +2 -0
  160. package/drizzle/0009_strong_marten_broadcloak.sql +19 -0
  161. package/drizzle/0010_needy_bishop.sql +11 -0
  162. package/drizzle/0011_moaning_millenium_guard.sql +1 -0
  163. package/drizzle/0012_late_marten_broadcloak.sql +2 -0
  164. package/drizzle/0013_previous_dormammu.sql +9 -0
  165. package/drizzle/0014_lazy_captain_universe.sql +2 -0
  166. package/drizzle/0015_zippy_wallop.sql +29 -0
  167. package/drizzle/0016_jazzy_zemo.sql +2 -0
  168. package/drizzle/0017_reflective_praxagora.sql +4 -0
  169. package/drizzle/0018_fat_vanisher.sql +22 -0
  170. package/drizzle/0019_new_clint_barton.sql +8 -0
  171. package/drizzle/0020_skinny_maverick.sql +1 -0
  172. package/drizzle/0021_mysterious_madelyne_pryor.sql +13 -0
  173. package/drizzle/0022_sleepy_ultimo.sql +25 -0
  174. package/drizzle/0023_wooden_mandrill.sql +2 -0
  175. package/drizzle/AGENTS.md +68 -0
  176. package/drizzle/CLAUDE.md +1 -0
  177. package/drizzle/meta/0000_snapshot.json +221 -0
  178. package/drizzle/meta/0001_snapshot.json +214 -0
  179. package/drizzle/meta/0002_snapshot.json +221 -0
  180. package/drizzle/meta/0005_snapshot.json +369 -0
  181. package/drizzle/meta/0006_snapshot.json +638 -0
  182. package/drizzle/meta/0007_snapshot.json +640 -0
  183. package/drizzle/meta/0008_snapshot.json +649 -0
  184. package/drizzle/meta/0009_snapshot.json +554 -0
  185. package/drizzle/meta/0010_snapshot.json +619 -0
  186. package/drizzle/meta/0011_snapshot.json +627 -0
  187. package/drizzle/meta/0012_snapshot.json +639 -0
  188. package/drizzle/meta/0013_snapshot.json +717 -0
  189. package/drizzle/meta/0014_snapshot.json +717 -0
  190. package/drizzle/meta/0015_snapshot.json +897 -0
  191. package/drizzle/meta/0016_snapshot.json +1031 -0
  192. package/drizzle/meta/0018_snapshot.json +1210 -0
  193. package/drizzle/meta/0019_snapshot.json +1165 -0
  194. package/drizzle/meta/0020_snapshot.json +1232 -0
  195. package/drizzle/meta/0021_snapshot.json +1311 -0
  196. package/drizzle/meta/0022_snapshot.json +1481 -0
  197. package/drizzle/meta/0023_snapshot.json +1496 -0
  198. package/drizzle/meta/_journal.json +174 -0
  199. package/package.json +240 -0
@@ -0,0 +1,315 @@
1
+ const require_logger = require("./logger-DyfK9PBt.cjs");
2
+ const require_fetch = require("./fetch-BTxakTSg.cjs");
3
+ const require_blobs = require("./blobs-BgcNn97m.cjs");
4
+ const require_text = require("./text-CW1cyrwj.cjs");
5
+ const require_base = require("./base-BEysXrkq.cjs");
6
+ let fs = require("fs");
7
+ fs = require_logger.__toESM(fs);
8
+ let path = require("path");
9
+ path = require_logger.__toESM(path);
10
+ //#region src/providers/bedrock/luma-ray.ts
11
+ /**
12
+ * Luma Ray 2 Video Generation Provider
13
+ *
14
+ * Supports text-to-video and image-to-video generation using AWS Bedrock's
15
+ * async invoke API. Videos can be 5 or 9 seconds with various aspect ratios.
16
+ */
17
+ const MODEL_ID = "luma.ray-v2:0";
18
+ const DEFAULT_DURATION = "5s";
19
+ const DEFAULT_RESOLUTION = "720p";
20
+ const DEFAULT_ASPECT_RATIO = "16:9";
21
+ const DEFAULT_POLL_INTERVAL_MS = 1e4;
22
+ const DEFAULT_MAX_POLL_TIME_MS = 6e5;
23
+ const VALID_ASPECT_RATIOS = [
24
+ "1:1",
25
+ "16:9",
26
+ "9:16",
27
+ "4:3",
28
+ "3:4",
29
+ "21:9",
30
+ "9:21"
31
+ ];
32
+ const VALID_DURATIONS = ["5s", "9s"];
33
+ const VALID_RESOLUTIONS = ["540p", "720p"];
34
+ var LumaRayVideoProvider = class extends require_base.AwsBedrockGenericProvider {
35
+ videoConfig;
36
+ providerId;
37
+ constructor(modelName = MODEL_ID, options = {}) {
38
+ super(modelName, options);
39
+ this.videoConfig = options.config || {};
40
+ this.providerId = options.id;
41
+ }
42
+ id() {
43
+ return this.providerId || `bedrock:video:${this.modelName}`;
44
+ }
45
+ toString() {
46
+ return `[Luma Ray 2 Video Provider ${this.modelName}]`;
47
+ }
48
+ /**
49
+ * Load image data from file:// path or return as-is if base64
50
+ */
51
+ loadImageData(imagePath) {
52
+ if (imagePath.startsWith("file://")) {
53
+ const filePath = imagePath.slice(7);
54
+ const resolvedPath = path.resolve(filePath);
55
+ if (filePath.includes("..") && resolvedPath !== path.resolve(path.normalize(filePath))) return { error: `Invalid image path (path traversal detected): ${filePath}` };
56
+ if (!fs.existsSync(resolvedPath)) return { error: `Image file not found: ${resolvedPath}` };
57
+ return { data: fs.readFileSync(resolvedPath).toString("base64") };
58
+ }
59
+ return { data: imagePath };
60
+ }
61
+ /**
62
+ * Detect image format from path or data
63
+ */
64
+ detectImageFormat(imagePath) {
65
+ const lowerPath = imagePath.toLowerCase();
66
+ if (lowerPath.includes(".png") || lowerPath.startsWith("ivborw")) return "image/png";
67
+ return "image/jpeg";
68
+ }
69
+ /**
70
+ * Build a keyframe from image path
71
+ */
72
+ buildKeyframe(imagePath) {
73
+ const { data, error } = this.loadImageData(imagePath);
74
+ if (error || !data) return { error: error || "Failed to load image" };
75
+ return { keyframe: {
76
+ type: "image",
77
+ source: {
78
+ type: "base64",
79
+ media_type: this.detectImageFormat(imagePath),
80
+ data
81
+ }
82
+ } };
83
+ }
84
+ /**
85
+ * Build keyframes from config convenience properties
86
+ */
87
+ buildKeyframes(config) {
88
+ if (config.keyframes) return { keyframes: config.keyframes };
89
+ const keyframes = {};
90
+ if (config.startImage) {
91
+ const { keyframe, error } = this.buildKeyframe(config.startImage);
92
+ if (error) return { error: `Start image error: ${error}` };
93
+ keyframes.frame0 = keyframe;
94
+ }
95
+ if (config.endImage) {
96
+ const { keyframe, error } = this.buildKeyframe(config.endImage);
97
+ if (error) return { error: `End image error: ${error}` };
98
+ keyframes.frame1 = keyframe;
99
+ }
100
+ if (Object.keys(keyframes).length === 0) return {};
101
+ return { keyframes };
102
+ }
103
+ /**
104
+ * Build model input for Luma Ray
105
+ */
106
+ buildModelInput(prompt, config) {
107
+ const aspectRatio = config.aspectRatio || DEFAULT_ASPECT_RATIO;
108
+ if (!VALID_ASPECT_RATIOS.includes(aspectRatio)) return { error: `Invalid aspect_ratio: ${aspectRatio}. Must be one of: ${VALID_ASPECT_RATIOS.join(", ")}` };
109
+ const duration = config.duration || DEFAULT_DURATION;
110
+ if (!VALID_DURATIONS.includes(duration)) return { error: `Invalid duration: ${duration}. Must be one of: ${VALID_DURATIONS.join(", ")}` };
111
+ const resolution = config.resolution || DEFAULT_RESOLUTION;
112
+ if (!VALID_RESOLUTIONS.includes(resolution)) return { error: `Invalid resolution: ${resolution}. Must be one of: ${VALID_RESOLUTIONS.join(", ")}` };
113
+ const { keyframes, error: keyframeError } = this.buildKeyframes(config);
114
+ if (keyframeError) return { error: keyframeError };
115
+ const modelInput = {
116
+ prompt,
117
+ aspect_ratio: aspectRatio,
118
+ duration,
119
+ resolution
120
+ };
121
+ if (config.loop !== void 0) modelInput.loop = config.loop;
122
+ if (keyframes) modelInput.keyframes = keyframes;
123
+ return { input: modelInput };
124
+ }
125
+ /**
126
+ * Start async video generation job
127
+ */
128
+ async startVideoGeneration(modelInput, s3OutputUri) {
129
+ try {
130
+ const { BedrockRuntimeClient, StartAsyncInvokeCommand } = await import("@aws-sdk/client-bedrock-runtime");
131
+ const credentials = await this.getCredentials();
132
+ const client = new BedrockRuntimeClient({
133
+ region: this.getRegion(),
134
+ ...credentials ? { credentials } : {}
135
+ });
136
+ const command = new StartAsyncInvokeCommand({
137
+ modelId: this.modelName,
138
+ modelInput,
139
+ outputDataConfig: { s3OutputDataConfig: { s3Uri: s3OutputUri } }
140
+ });
141
+ return { invocationArn: (await client.send(command)).invocationArn };
142
+ } catch (err) {
143
+ const error = err;
144
+ require_logger.logger.error("[Luma Ray] Failed to start video generation", { error });
145
+ return { error: `Failed to start video generation: ${error.message || String(err)}` };
146
+ }
147
+ }
148
+ /**
149
+ * Poll for job completion
150
+ */
151
+ async pollForCompletion(invocationArn, pollIntervalMs, maxPollTimeMs) {
152
+ const startTime = Date.now();
153
+ try {
154
+ const { BedrockRuntimeClient, GetAsyncInvokeCommand } = await import("@aws-sdk/client-bedrock-runtime");
155
+ const credentials = await this.getCredentials();
156
+ const client = new BedrockRuntimeClient({
157
+ region: this.getRegion(),
158
+ ...credentials ? { credentials } : {}
159
+ });
160
+ while (Date.now() - startTime < maxPollTimeMs) {
161
+ const command = new GetAsyncInvokeCommand({ invocationArn });
162
+ const invocation = await client.send(command);
163
+ require_logger.logger.debug(`[Luma Ray] Job status: ${invocation.status}`, {
164
+ invocationArn,
165
+ elapsedMs: Date.now() - startTime
166
+ });
167
+ if (invocation.status === "Completed") return { response: {
168
+ invocationArn: invocation.invocationArn || invocationArn,
169
+ status: "Completed",
170
+ submitTime: invocation.submitTime?.toISOString(),
171
+ endTime: invocation.endTime?.toISOString(),
172
+ outputDataConfig: invocation.outputDataConfig
173
+ } };
174
+ if (invocation.status === "Failed") return { error: `Video generation failed: ${invocation.failureMessage}` };
175
+ await require_fetch.sleep(pollIntervalMs);
176
+ }
177
+ return { error: `Video generation timed out after ${maxPollTimeMs / 1e3} seconds` };
178
+ } catch (err) {
179
+ const error = err;
180
+ require_logger.logger.error("[Luma Ray] Polling error", {
181
+ error,
182
+ invocationArn
183
+ });
184
+ return { error: `Polling error: ${error.message || String(err)}` };
185
+ }
186
+ }
187
+ /**
188
+ * Download video from S3 and store to blob storage
189
+ */
190
+ async downloadAndStoreVideo(s3Uri) {
191
+ try {
192
+ const match = s3Uri.match(/^s3:\/\/([^/]+)\/(.+)$/);
193
+ if (!match) return { error: `Invalid S3 URI: ${s3Uri}` };
194
+ const [, bucket, keyPrefix] = match;
195
+ const { S3Client, GetObjectCommand } = await import("@aws-sdk/client-s3");
196
+ const credentials = await this.getCredentials();
197
+ const s3 = new S3Client({
198
+ region: this.getRegion(),
199
+ ...credentials ? { credentials } : {}
200
+ });
201
+ const videoKey = keyPrefix.endsWith("/") ? `${keyPrefix}output.mp4` : `${keyPrefix}/output.mp4`;
202
+ require_logger.logger.debug("[Luma Ray] Downloading video from S3", {
203
+ bucket,
204
+ key: videoKey
205
+ });
206
+ const response = await s3.send(new GetObjectCommand({
207
+ Bucket: bucket,
208
+ Key: videoKey
209
+ }));
210
+ if (!response.Body) return { error: "Empty response from S3" };
211
+ const { ref } = await require_blobs.storeBlob(Buffer.from(await response.Body.transformToByteArray()), "video/mp4", {
212
+ kind: "video",
213
+ location: "response.video"
214
+ });
215
+ require_logger.logger.debug("[Luma Ray] Stored video to blob storage", {
216
+ uri: ref.uri,
217
+ hash: ref.hash
218
+ });
219
+ return { blobRef: ref };
220
+ } catch (err) {
221
+ const error = err;
222
+ require_logger.logger.error("[Luma Ray] S3 download error", {
223
+ error,
224
+ s3Uri
225
+ });
226
+ if (error.name === "MODULE_NOT_FOUND" || String(err).includes("Cannot find module")) return { error: "The @aws-sdk/client-s3 package is required for Luma Ray video downloads. Install it with: npm install @aws-sdk/client-s3" };
227
+ return { error: `S3 download error: ${error.message || String(err)}` };
228
+ }
229
+ }
230
+ /**
231
+ * Get video dimensions from aspect ratio
232
+ */
233
+ getVideoDimensions(aspectRatio, resolution) {
234
+ const height = resolution === "540p" ? 540 : 720;
235
+ const aspectParts = aspectRatio.split(":").map(Number);
236
+ return `${Math.round(height * aspectParts[0] / aspectParts[1])}x${height}`;
237
+ }
238
+ /**
239
+ * Get duration in seconds from duration string
240
+ */
241
+ getDurationSeconds(duration) {
242
+ return duration === "9s" ? 9 : 5;
243
+ }
244
+ async callApi(prompt, context) {
245
+ const s3OutputUri = this.videoConfig.s3OutputUri;
246
+ if (!s3OutputUri) return { error: "Luma Ray requires s3OutputUri in provider config. Example: s3://my-bucket/videos/" };
247
+ if (!s3OutputUri.startsWith("s3://")) return { error: `Invalid s3OutputUri: ${s3OutputUri}. Must start with s3://` };
248
+ if (!prompt || prompt.trim() === "") return { error: "Prompt is required for video generation" };
249
+ if (prompt.length > 5e3) return { error: `Prompt exceeds 5000 character limit. Got: ${prompt.length}` };
250
+ const config = {
251
+ ...this.videoConfig,
252
+ ...context?.prompt?.config
253
+ };
254
+ const startTime = Date.now();
255
+ const { input: modelInput, error: buildError } = this.buildModelInput(prompt, config);
256
+ if (buildError || !modelInput) return { error: buildError || "Failed to build model input" };
257
+ require_logger.logger.info("[Luma Ray] Starting video generation job...", {
258
+ duration: config.duration || DEFAULT_DURATION,
259
+ resolution: config.resolution || DEFAULT_RESOLUTION,
260
+ aspectRatio: config.aspectRatio || DEFAULT_ASPECT_RATIO,
261
+ s3OutputUri
262
+ });
263
+ const { invocationArn, error: startError } = await this.startVideoGeneration(modelInput, s3OutputUri);
264
+ if (startError || !invocationArn) return { error: startError || "Failed to start video generation" };
265
+ require_logger.logger.info("[Luma Ray] Job started", { invocationArn });
266
+ const pollIntervalMs = config.pollIntervalMs || DEFAULT_POLL_INTERVAL_MS;
267
+ const maxPollTimeMs = config.maxPollTimeMs || DEFAULT_MAX_POLL_TIME_MS;
268
+ const { response, error: pollError } = await this.pollForCompletion(invocationArn, pollIntervalMs, maxPollTimeMs);
269
+ if (pollError || !response) return { error: pollError || "Polling failed" };
270
+ const outputS3Uri = response.outputDataConfig?.s3OutputDataConfig?.s3Uri;
271
+ if (!outputS3Uri) return { error: "No output location in response" };
272
+ let blobRef;
273
+ const outputUrl = `${outputS3Uri}/output.mp4`;
274
+ if (config.downloadFromS3 !== false) {
275
+ const { blobRef: ref, error: downloadError } = await this.downloadAndStoreVideo(outputS3Uri);
276
+ if (downloadError) require_logger.logger.warn(`[Luma Ray] Failed to download video: ${downloadError}. Using S3 URL.`);
277
+ else blobRef = ref;
278
+ }
279
+ const latencyMs = Date.now() - startTime;
280
+ const duration = config.duration || DEFAULT_DURATION;
281
+ const resolution = config.resolution || DEFAULT_RESOLUTION;
282
+ const aspectRatio = config.aspectRatio || DEFAULT_ASPECT_RATIO;
283
+ const durationSeconds = this.getDurationSeconds(duration);
284
+ const dimensions = this.getVideoDimensions(aspectRatio, resolution);
285
+ return {
286
+ output: `[Video: ${require_text.ellipsize(prompt.replace(/\r?\n|\r/g, " ").replace(/\[/g, "(").replace(/\]/g, ")"), 50)}](${blobRef?.uri || outputUrl})`,
287
+ cached: false,
288
+ latencyMs,
289
+ video: {
290
+ id: invocationArn,
291
+ blobRef,
292
+ url: blobRef ? void 0 : outputUrl,
293
+ format: "mp4",
294
+ size: dimensions,
295
+ duration: durationSeconds,
296
+ model: this.modelName,
297
+ resolution: dimensions
298
+ },
299
+ metadata: {
300
+ invocationArn,
301
+ model: this.modelName,
302
+ duration,
303
+ resolution,
304
+ aspectRatio,
305
+ loop: config.loop,
306
+ s3OutputUri: outputS3Uri,
307
+ ...blobRef && { blobHash: blobRef.hash }
308
+ }
309
+ };
310
+ }
311
+ };
312
+ //#endregion
313
+ exports.LumaRayVideoProvider = LumaRayVideoProvider;
314
+
315
+ //# sourceMappingURL=luma-ray-BAU9X_ep.cjs.map
@@ -0,0 +1,313 @@
1
+ import { r as logger } from "./logger-C40ZGil9.js";
2
+ import { d as sleep } from "./fetch-DQckpUFz.js";
3
+ import { n as storeBlob } from "./blobs-BY8MDmpo.js";
4
+ import { t as ellipsize } from "./text-B_UCRPp2.js";
5
+ import { t as AwsBedrockGenericProvider } from "./base-C451JQfq.js";
6
+ import * as fs$1 from "fs";
7
+ import * as path$1 from "path";
8
+ //#region src/providers/bedrock/luma-ray.ts
9
+ /**
10
+ * Luma Ray 2 Video Generation Provider
11
+ *
12
+ * Supports text-to-video and image-to-video generation using AWS Bedrock's
13
+ * async invoke API. Videos can be 5 or 9 seconds with various aspect ratios.
14
+ */
15
+ const MODEL_ID = "luma.ray-v2:0";
16
+ const DEFAULT_DURATION = "5s";
17
+ const DEFAULT_RESOLUTION = "720p";
18
+ const DEFAULT_ASPECT_RATIO = "16:9";
19
+ const DEFAULT_POLL_INTERVAL_MS = 1e4;
20
+ const DEFAULT_MAX_POLL_TIME_MS = 6e5;
21
+ const VALID_ASPECT_RATIOS = [
22
+ "1:1",
23
+ "16:9",
24
+ "9:16",
25
+ "4:3",
26
+ "3:4",
27
+ "21:9",
28
+ "9:21"
29
+ ];
30
+ const VALID_DURATIONS = ["5s", "9s"];
31
+ const VALID_RESOLUTIONS = ["540p", "720p"];
32
+ var LumaRayVideoProvider = class extends AwsBedrockGenericProvider {
33
+ videoConfig;
34
+ providerId;
35
+ constructor(modelName = MODEL_ID, options = {}) {
36
+ super(modelName, options);
37
+ this.videoConfig = options.config || {};
38
+ this.providerId = options.id;
39
+ }
40
+ id() {
41
+ return this.providerId || `bedrock:video:${this.modelName}`;
42
+ }
43
+ toString() {
44
+ return `[Luma Ray 2 Video Provider ${this.modelName}]`;
45
+ }
46
+ /**
47
+ * Load image data from file:// path or return as-is if base64
48
+ */
49
+ loadImageData(imagePath) {
50
+ if (imagePath.startsWith("file://")) {
51
+ const filePath = imagePath.slice(7);
52
+ const resolvedPath = path$1.resolve(filePath);
53
+ if (filePath.includes("..") && resolvedPath !== path$1.resolve(path$1.normalize(filePath))) return { error: `Invalid image path (path traversal detected): ${filePath}` };
54
+ if (!fs$1.existsSync(resolvedPath)) return { error: `Image file not found: ${resolvedPath}` };
55
+ return { data: fs$1.readFileSync(resolvedPath).toString("base64") };
56
+ }
57
+ return { data: imagePath };
58
+ }
59
+ /**
60
+ * Detect image format from path or data
61
+ */
62
+ detectImageFormat(imagePath) {
63
+ const lowerPath = imagePath.toLowerCase();
64
+ if (lowerPath.includes(".png") || lowerPath.startsWith("ivborw")) return "image/png";
65
+ return "image/jpeg";
66
+ }
67
+ /**
68
+ * Build a keyframe from image path
69
+ */
70
+ buildKeyframe(imagePath) {
71
+ const { data, error } = this.loadImageData(imagePath);
72
+ if (error || !data) return { error: error || "Failed to load image" };
73
+ return { keyframe: {
74
+ type: "image",
75
+ source: {
76
+ type: "base64",
77
+ media_type: this.detectImageFormat(imagePath),
78
+ data
79
+ }
80
+ } };
81
+ }
82
+ /**
83
+ * Build keyframes from config convenience properties
84
+ */
85
+ buildKeyframes(config) {
86
+ if (config.keyframes) return { keyframes: config.keyframes };
87
+ const keyframes = {};
88
+ if (config.startImage) {
89
+ const { keyframe, error } = this.buildKeyframe(config.startImage);
90
+ if (error) return { error: `Start image error: ${error}` };
91
+ keyframes.frame0 = keyframe;
92
+ }
93
+ if (config.endImage) {
94
+ const { keyframe, error } = this.buildKeyframe(config.endImage);
95
+ if (error) return { error: `End image error: ${error}` };
96
+ keyframes.frame1 = keyframe;
97
+ }
98
+ if (Object.keys(keyframes).length === 0) return {};
99
+ return { keyframes };
100
+ }
101
+ /**
102
+ * Build model input for Luma Ray
103
+ */
104
+ buildModelInput(prompt, config) {
105
+ const aspectRatio = config.aspectRatio || DEFAULT_ASPECT_RATIO;
106
+ if (!VALID_ASPECT_RATIOS.includes(aspectRatio)) return { error: `Invalid aspect_ratio: ${aspectRatio}. Must be one of: ${VALID_ASPECT_RATIOS.join(", ")}` };
107
+ const duration = config.duration || DEFAULT_DURATION;
108
+ if (!VALID_DURATIONS.includes(duration)) return { error: `Invalid duration: ${duration}. Must be one of: ${VALID_DURATIONS.join(", ")}` };
109
+ const resolution = config.resolution || DEFAULT_RESOLUTION;
110
+ if (!VALID_RESOLUTIONS.includes(resolution)) return { error: `Invalid resolution: ${resolution}. Must be one of: ${VALID_RESOLUTIONS.join(", ")}` };
111
+ const { keyframes, error: keyframeError } = this.buildKeyframes(config);
112
+ if (keyframeError) return { error: keyframeError };
113
+ const modelInput = {
114
+ prompt,
115
+ aspect_ratio: aspectRatio,
116
+ duration,
117
+ resolution
118
+ };
119
+ if (config.loop !== void 0) modelInput.loop = config.loop;
120
+ if (keyframes) modelInput.keyframes = keyframes;
121
+ return { input: modelInput };
122
+ }
123
+ /**
124
+ * Start async video generation job
125
+ */
126
+ async startVideoGeneration(modelInput, s3OutputUri) {
127
+ try {
128
+ const { BedrockRuntimeClient, StartAsyncInvokeCommand } = await import("@aws-sdk/client-bedrock-runtime");
129
+ const credentials = await this.getCredentials();
130
+ const client = new BedrockRuntimeClient({
131
+ region: this.getRegion(),
132
+ ...credentials ? { credentials } : {}
133
+ });
134
+ const command = new StartAsyncInvokeCommand({
135
+ modelId: this.modelName,
136
+ modelInput,
137
+ outputDataConfig: { s3OutputDataConfig: { s3Uri: s3OutputUri } }
138
+ });
139
+ return { invocationArn: (await client.send(command)).invocationArn };
140
+ } catch (err) {
141
+ const error = err;
142
+ logger.error("[Luma Ray] Failed to start video generation", { error });
143
+ return { error: `Failed to start video generation: ${error.message || String(err)}` };
144
+ }
145
+ }
146
+ /**
147
+ * Poll for job completion
148
+ */
149
+ async pollForCompletion(invocationArn, pollIntervalMs, maxPollTimeMs) {
150
+ const startTime = Date.now();
151
+ try {
152
+ const { BedrockRuntimeClient, GetAsyncInvokeCommand } = await import("@aws-sdk/client-bedrock-runtime");
153
+ const credentials = await this.getCredentials();
154
+ const client = new BedrockRuntimeClient({
155
+ region: this.getRegion(),
156
+ ...credentials ? { credentials } : {}
157
+ });
158
+ while (Date.now() - startTime < maxPollTimeMs) {
159
+ const command = new GetAsyncInvokeCommand({ invocationArn });
160
+ const invocation = await client.send(command);
161
+ logger.debug(`[Luma Ray] Job status: ${invocation.status}`, {
162
+ invocationArn,
163
+ elapsedMs: Date.now() - startTime
164
+ });
165
+ if (invocation.status === "Completed") return { response: {
166
+ invocationArn: invocation.invocationArn || invocationArn,
167
+ status: "Completed",
168
+ submitTime: invocation.submitTime?.toISOString(),
169
+ endTime: invocation.endTime?.toISOString(),
170
+ outputDataConfig: invocation.outputDataConfig
171
+ } };
172
+ if (invocation.status === "Failed") return { error: `Video generation failed: ${invocation.failureMessage}` };
173
+ await sleep(pollIntervalMs);
174
+ }
175
+ return { error: `Video generation timed out after ${maxPollTimeMs / 1e3} seconds` };
176
+ } catch (err) {
177
+ const error = err;
178
+ logger.error("[Luma Ray] Polling error", {
179
+ error,
180
+ invocationArn
181
+ });
182
+ return { error: `Polling error: ${error.message || String(err)}` };
183
+ }
184
+ }
185
+ /**
186
+ * Download video from S3 and store to blob storage
187
+ */
188
+ async downloadAndStoreVideo(s3Uri) {
189
+ try {
190
+ const match = s3Uri.match(/^s3:\/\/([^/]+)\/(.+)$/);
191
+ if (!match) return { error: `Invalid S3 URI: ${s3Uri}` };
192
+ const [, bucket, keyPrefix] = match;
193
+ const { S3Client, GetObjectCommand } = await import("@aws-sdk/client-s3");
194
+ const credentials = await this.getCredentials();
195
+ const s3 = new S3Client({
196
+ region: this.getRegion(),
197
+ ...credentials ? { credentials } : {}
198
+ });
199
+ const videoKey = keyPrefix.endsWith("/") ? `${keyPrefix}output.mp4` : `${keyPrefix}/output.mp4`;
200
+ logger.debug("[Luma Ray] Downloading video from S3", {
201
+ bucket,
202
+ key: videoKey
203
+ });
204
+ const response = await s3.send(new GetObjectCommand({
205
+ Bucket: bucket,
206
+ Key: videoKey
207
+ }));
208
+ if (!response.Body) return { error: "Empty response from S3" };
209
+ const { ref } = await storeBlob(Buffer.from(await response.Body.transformToByteArray()), "video/mp4", {
210
+ kind: "video",
211
+ location: "response.video"
212
+ });
213
+ logger.debug("[Luma Ray] Stored video to blob storage", {
214
+ uri: ref.uri,
215
+ hash: ref.hash
216
+ });
217
+ return { blobRef: ref };
218
+ } catch (err) {
219
+ const error = err;
220
+ logger.error("[Luma Ray] S3 download error", {
221
+ error,
222
+ s3Uri
223
+ });
224
+ if (error.name === "MODULE_NOT_FOUND" || String(err).includes("Cannot find module")) return { error: "The @aws-sdk/client-s3 package is required for Luma Ray video downloads. Install it with: npm install @aws-sdk/client-s3" };
225
+ return { error: `S3 download error: ${error.message || String(err)}` };
226
+ }
227
+ }
228
+ /**
229
+ * Get video dimensions from aspect ratio
230
+ */
231
+ getVideoDimensions(aspectRatio, resolution) {
232
+ const height = resolution === "540p" ? 540 : 720;
233
+ const aspectParts = aspectRatio.split(":").map(Number);
234
+ return `${Math.round(height * aspectParts[0] / aspectParts[1])}x${height}`;
235
+ }
236
+ /**
237
+ * Get duration in seconds from duration string
238
+ */
239
+ getDurationSeconds(duration) {
240
+ return duration === "9s" ? 9 : 5;
241
+ }
242
+ async callApi(prompt, context) {
243
+ const s3OutputUri = this.videoConfig.s3OutputUri;
244
+ if (!s3OutputUri) return { error: "Luma Ray requires s3OutputUri in provider config. Example: s3://my-bucket/videos/" };
245
+ if (!s3OutputUri.startsWith("s3://")) return { error: `Invalid s3OutputUri: ${s3OutputUri}. Must start with s3://` };
246
+ if (!prompt || prompt.trim() === "") return { error: "Prompt is required for video generation" };
247
+ if (prompt.length > 5e3) return { error: `Prompt exceeds 5000 character limit. Got: ${prompt.length}` };
248
+ const config = {
249
+ ...this.videoConfig,
250
+ ...context?.prompt?.config
251
+ };
252
+ const startTime = Date.now();
253
+ const { input: modelInput, error: buildError } = this.buildModelInput(prompt, config);
254
+ if (buildError || !modelInput) return { error: buildError || "Failed to build model input" };
255
+ logger.info("[Luma Ray] Starting video generation job...", {
256
+ duration: config.duration || DEFAULT_DURATION,
257
+ resolution: config.resolution || DEFAULT_RESOLUTION,
258
+ aspectRatio: config.aspectRatio || DEFAULT_ASPECT_RATIO,
259
+ s3OutputUri
260
+ });
261
+ const { invocationArn, error: startError } = await this.startVideoGeneration(modelInput, s3OutputUri);
262
+ if (startError || !invocationArn) return { error: startError || "Failed to start video generation" };
263
+ logger.info("[Luma Ray] Job started", { invocationArn });
264
+ const pollIntervalMs = config.pollIntervalMs || DEFAULT_POLL_INTERVAL_MS;
265
+ const maxPollTimeMs = config.maxPollTimeMs || DEFAULT_MAX_POLL_TIME_MS;
266
+ const { response, error: pollError } = await this.pollForCompletion(invocationArn, pollIntervalMs, maxPollTimeMs);
267
+ if (pollError || !response) return { error: pollError || "Polling failed" };
268
+ const outputS3Uri = response.outputDataConfig?.s3OutputDataConfig?.s3Uri;
269
+ if (!outputS3Uri) return { error: "No output location in response" };
270
+ let blobRef;
271
+ const outputUrl = `${outputS3Uri}/output.mp4`;
272
+ if (config.downloadFromS3 !== false) {
273
+ const { blobRef: ref, error: downloadError } = await this.downloadAndStoreVideo(outputS3Uri);
274
+ if (downloadError) logger.warn(`[Luma Ray] Failed to download video: ${downloadError}. Using S3 URL.`);
275
+ else blobRef = ref;
276
+ }
277
+ const latencyMs = Date.now() - startTime;
278
+ const duration = config.duration || DEFAULT_DURATION;
279
+ const resolution = config.resolution || DEFAULT_RESOLUTION;
280
+ const aspectRatio = config.aspectRatio || DEFAULT_ASPECT_RATIO;
281
+ const durationSeconds = this.getDurationSeconds(duration);
282
+ const dimensions = this.getVideoDimensions(aspectRatio, resolution);
283
+ return {
284
+ output: `[Video: ${ellipsize(prompt.replace(/\r?\n|\r/g, " ").replace(/\[/g, "(").replace(/\]/g, ")"), 50)}](${blobRef?.uri || outputUrl})`,
285
+ cached: false,
286
+ latencyMs,
287
+ video: {
288
+ id: invocationArn,
289
+ blobRef,
290
+ url: blobRef ? void 0 : outputUrl,
291
+ format: "mp4",
292
+ size: dimensions,
293
+ duration: durationSeconds,
294
+ model: this.modelName,
295
+ resolution: dimensions
296
+ },
297
+ metadata: {
298
+ invocationArn,
299
+ model: this.modelName,
300
+ duration,
301
+ resolution,
302
+ aspectRatio,
303
+ loop: config.loop,
304
+ s3OutputUri: outputS3Uri,
305
+ ...blobRef && { blobHash: blobRef.hash }
306
+ }
307
+ };
308
+ }
309
+ };
310
+ //#endregion
311
+ export { LumaRayVideoProvider };
312
+
313
+ //# sourceMappingURL=luma-ray-nwVseBbv.js.map