const require_rolldown_runtime = require("./rolldown-runtime-D_mwlA32.cjs");
const require_logger = require("./logger-DuG3amVa.cjs");
const require_time = require("./time-C8D2VmK1.cjs");
const require_blobs = require("./blobs-BKxNc-PT.cjs");
const require_text = require("./text-Bxg2HNQm.cjs");
const require_base = require("./base-CyV2DLfI.cjs");
let path = require("path");
path = require_rolldown_runtime.__toESM(path, 1);
let fs = require("fs");
fs = require_rolldown_runtime.__toESM(fs, 1);
//#region src/providers/bedrock/luma-ray.ts
/**
* Luma Ray 2 Video Generation Provider
*
* Supports text-to-video and image-to-video generation using AWS Bedrock's
* async invoke API. Videos can be 5 or 9 seconds with various aspect ratios.
*/
const MODEL_ID = "luma.ray-v2:0";
const DEFAULT_DURATION = "5s";
const DEFAULT_RESOLUTION = "720p";
const DEFAULT_ASPECT_RATIO = "16:9";
const DEFAULT_POLL_INTERVAL_MS = 1e4;
const DEFAULT_MAX_POLL_TIME_MS = 6e5;
const VALID_ASPECT_RATIOS = [
	"1:1",
	"16:9",
	"9:16",
	"4:3",
	"3:4",
	"21:9",
	"9:21"
];
const VALID_DURATIONS = ["5s", "9s"];
const VALID_RESOLUTIONS = ["540p", "720p"];
var LumaRayVideoProvider = class extends require_base.AwsBedrockGenericProvider {
	videoConfig;
	providerId;
	constructor(modelName = MODEL_ID, options = {}) {
		super(modelName, options);
		this.videoConfig = options.config || {};
		this.providerId = options.id;
	}
	id() {
		return this.providerId || `bedrock:video:${this.modelName}`;
	}
	toString() {
		return `[Luma Ray 2 Video Provider ${this.modelName}]`;
	}
	/**
	* Load image data from file:// path or return as-is if base64
	*/
	loadImageData(imagePath) {
		if (imagePath.startsWith("file://")) {
			const filePath = imagePath.slice(7);
			const resolvedPath = path.resolve(filePath);
			if (filePath.includes("..") && resolvedPath !== path.resolve(path.normalize(filePath))) return { error: `Invalid image path (path traversal detected): ${filePath}` };
			if (!fs.existsSync(resolvedPath)) return { error: `Image file not found: ${resolvedPath}` };
			return { data: fs.readFileSync(resolvedPath).toString("base64") };
		}
		return { data: imagePath };
	}
	/**
	* Detect image format from path or data
	*/
	detectImageFormat(imagePath) {
		const lowerPath = imagePath.toLowerCase();
		if (lowerPath.includes(".png") || lowerPath.startsWith("ivborw")) return "image/png";
		return "image/jpeg";
	}
	/**
	* Build a keyframe from image path
	*/
	buildKeyframe(imagePath) {
		const { data, error } = this.loadImageData(imagePath);
		if (error || !data) return { error: error || "Failed to load image" };
		return { keyframe: {
			type: "image",
			source: {
				type: "base64",
				media_type: this.detectImageFormat(imagePath),
				data
			}
		} };
	}
	/**
	* Build keyframes from config convenience properties
	*/
	buildKeyframes(config) {
		if (config.keyframes) return { keyframes: config.keyframes };
		const keyframes = {};
		if (config.startImage) {
			const { keyframe, error } = this.buildKeyframe(config.startImage);
			if (error) return { error: `Start image error: ${error}` };
			keyframes.frame0 = keyframe;
		}
		if (config.endImage) {
			const { keyframe, error } = this.buildKeyframe(config.endImage);
			if (error) return { error: `End image error: ${error}` };
			keyframes.frame1 = keyframe;
		}
		if (Object.keys(keyframes).length === 0) return {};
		return { keyframes };
	}
	/**
	* Build model input for Luma Ray
	*/
	buildModelInput(prompt, config) {
		const aspectRatio = config.aspectRatio || DEFAULT_ASPECT_RATIO;
		if (!VALID_ASPECT_RATIOS.includes(aspectRatio)) return { error: `Invalid aspect_ratio: ${aspectRatio}. Must be one of: ${VALID_ASPECT_RATIOS.join(", ")}` };
		const duration = config.duration || DEFAULT_DURATION;
		if (!VALID_DURATIONS.includes(duration)) return { error: `Invalid duration: ${duration}. Must be one of: ${VALID_DURATIONS.join(", ")}` };
		const resolution = config.resolution || DEFAULT_RESOLUTION;
		if (!VALID_RESOLUTIONS.includes(resolution)) return { error: `Invalid resolution: ${resolution}. Must be one of: ${VALID_RESOLUTIONS.join(", ")}` };
		const { keyframes, error: keyframeError } = this.buildKeyframes(config);
		if (keyframeError) return { error: keyframeError };
		const modelInput = {
			prompt,
			aspect_ratio: aspectRatio,
			duration,
			resolution
		};
		if (config.loop !== void 0) modelInput.loop = config.loop;
		if (keyframes) modelInput.keyframes = keyframes;
		return { input: modelInput };
	}
	/**
	* Start async video generation job
	*/
	async startVideoGeneration(modelInput, s3OutputUri) {
		try {
			const { BedrockRuntimeClient, StartAsyncInvokeCommand } = await import("@aws-sdk/client-bedrock-runtime");
			const credentials = await this.getCredentials();
			const client = new BedrockRuntimeClient({
				region: this.getRegion(),
				...credentials ? { credentials } : {}
			});
			const command = new StartAsyncInvokeCommand({
				modelId: this.modelName,
				modelInput,
				outputDataConfig: { s3OutputDataConfig: { s3Uri: s3OutputUri } }
			});
			return { invocationArn: (await client.send(command)).invocationArn };
		} catch (err) {
			const error = err;
			require_logger.logger.error("[Luma Ray] Failed to start video generation", { error });
			return { error: `Failed to start video generation: ${error.message || String(err)}` };
		}
	}
	/**
	* Poll for job completion
	*/
	async pollForCompletion(invocationArn, pollIntervalMs, maxPollTimeMs) {
		const startTime = Date.now();
		try {
			const { BedrockRuntimeClient, GetAsyncInvokeCommand } = await import("@aws-sdk/client-bedrock-runtime");
			const credentials = await this.getCredentials();
			const client = new BedrockRuntimeClient({
				region: this.getRegion(),
				...credentials ? { credentials } : {}
			});
			while (Date.now() - startTime < maxPollTimeMs) {
				const command = new GetAsyncInvokeCommand({ invocationArn });
				const invocation = await client.send(command);
				require_logger.logger.debug(`[Luma Ray] Job status: ${invocation.status}`, {
					invocationArn,
					elapsedMs: Date.now() - startTime
				});
				if (invocation.status === "Completed") return { response: {
					invocationArn: invocation.invocationArn || invocationArn,
					status: "Completed",
					submitTime: invocation.submitTime?.toISOString(),
					endTime: invocation.endTime?.toISOString(),
					outputDataConfig: invocation.outputDataConfig
				} };
				if (invocation.status === "Failed") return { error: `Video generation failed: ${invocation.failureMessage}` };
				await require_time.sleep(pollIntervalMs);
			}
			return { error: `Video generation timed out after ${maxPollTimeMs / 1e3} seconds` };
		} catch (err) {
			const error = err;
			require_logger.logger.error("[Luma Ray] Polling error", {
				error,
				invocationArn
			});
			return { error: `Polling error: ${error.message || String(err)}` };
		}
	}
	/**
	* Download video from S3 and store to blob storage
	*/
	async downloadAndStoreVideo(s3Uri) {
		try {
			const match = s3Uri.match(/^s3:\/\/([^/]+)\/(.+)$/);
			if (!match) return { error: `Invalid S3 URI: ${s3Uri}` };
			const [, bucket, keyPrefix] = match;
			const { S3Client, GetObjectCommand } = await import("@aws-sdk/client-s3");
			const credentials = await this.getCredentials();
			const s3 = new S3Client({
				region: this.getRegion(),
				...credentials ? { credentials } : {}
			});
			const videoKey = keyPrefix.endsWith("/") ? `${keyPrefix}output.mp4` : `${keyPrefix}/output.mp4`;
			require_logger.logger.debug("[Luma Ray] Downloading video from S3", {
				bucket,
				key: videoKey
			});
			const response = await s3.send(new GetObjectCommand({
				Bucket: bucket,
				Key: videoKey
			}));
			if (!response.Body) return { error: "Empty response from S3" };
			const { ref } = await require_blobs.storeBlob(Buffer.from(await response.Body.transformToByteArray()), "video/mp4", {
				kind: "video",
				location: "response.video"
			});
			require_logger.logger.debug("[Luma Ray] Stored video to blob storage", {
				uri: ref.uri,
				hash: ref.hash
			});
			return { blobRef: ref };
		} catch (err) {
			const error = err;
			require_logger.logger.error("[Luma Ray] S3 download error", {
				error,
				s3Uri
			});
			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" };
			return { error: `S3 download error: ${error.message || String(err)}` };
		}
	}
	/**
	* Get video dimensions from aspect ratio
	*/
	getVideoDimensions(aspectRatio, resolution) {
		const height = resolution === "540p" ? 540 : 720;
		const aspectParts = aspectRatio.split(":").map(Number);
		return `${Math.round(height * aspectParts[0] / aspectParts[1])}x${height}`;
	}
	/**
	* Get duration in seconds from duration string
	*/
	getDurationSeconds(duration) {
		return duration === "9s" ? 9 : 5;
	}
	async callApi(prompt, context) {
		const s3OutputUri = this.videoConfig.s3OutputUri;
		if (!s3OutputUri) return { error: "Luma Ray requires s3OutputUri in provider config. Example: s3://my-bucket/videos/" };
		if (!s3OutputUri.startsWith("s3://")) return { error: `Invalid s3OutputUri: ${s3OutputUri}. Must start with s3://` };
		if (!prompt || prompt.trim() === "") return { error: "Prompt is required for video generation" };
		if (prompt.length > 5e3) return { error: `Prompt exceeds 5000 character limit. Got: ${prompt.length}` };
		const config = {
			...this.videoConfig,
			...context?.prompt?.config
		};
		const startTime = Date.now();
		const { input: modelInput, error: buildError } = this.buildModelInput(prompt, config);
		if (buildError || !modelInput) return { error: buildError || "Failed to build model input" };
		require_logger.logger.info("[Luma Ray] Starting video generation job...", {
			duration: config.duration || DEFAULT_DURATION,
			resolution: config.resolution || DEFAULT_RESOLUTION,
			aspectRatio: config.aspectRatio || DEFAULT_ASPECT_RATIO,
			s3OutputUri
		});
		const { invocationArn, error: startError } = await this.startVideoGeneration(modelInput, s3OutputUri);
		if (startError || !invocationArn) return { error: startError || "Failed to start video generation" };
		require_logger.logger.info("[Luma Ray] Job started", { invocationArn });
		const pollIntervalMs = config.pollIntervalMs || DEFAULT_POLL_INTERVAL_MS;
		const maxPollTimeMs = config.maxPollTimeMs || DEFAULT_MAX_POLL_TIME_MS;
		const { response, error: pollError } = await this.pollForCompletion(invocationArn, pollIntervalMs, maxPollTimeMs);
		if (pollError || !response) return { error: pollError || "Polling failed" };
		const outputS3Uri = response.outputDataConfig?.s3OutputDataConfig?.s3Uri;
		if (!outputS3Uri) return { error: "No output location in response" };
		let blobRef;
		const outputUrl = `${outputS3Uri}/output.mp4`;
		if (config.downloadFromS3 !== false) {
			const { blobRef: ref, error: downloadError } = await this.downloadAndStoreVideo(outputS3Uri);
			if (downloadError) require_logger.logger.warn(`[Luma Ray] Failed to download video: ${downloadError}. Using S3 URL.`);
			else blobRef = ref;
		}
		const latencyMs = Date.now() - startTime;
		const duration = config.duration || DEFAULT_DURATION;
		const resolution = config.resolution || DEFAULT_RESOLUTION;
		const aspectRatio = config.aspectRatio || DEFAULT_ASPECT_RATIO;
		const durationSeconds = this.getDurationSeconds(duration);
		const dimensions = this.getVideoDimensions(aspectRatio, resolution);
		return {
			output: `[Video: ${require_text.ellipsize(prompt.replace(/\r?\n|\r/g, " ").replace(/\[/g, "(").replace(/\]/g, ")"), 50)}](${blobRef?.uri || outputUrl})`,
			cached: false,
			latencyMs,
			video: {
				id: invocationArn,
				blobRef,
				url: blobRef ? void 0 : outputUrl,
				format: "mp4",
				size: dimensions,
				duration: durationSeconds,
				model: this.modelName,
				resolution: dimensions
			},
			metadata: {
				invocationArn,
				model: this.modelName,
				duration,
				resolution,
				aspectRatio,
				loop: config.loop,
				s3OutputUri: outputS3Uri,
				...blobRef && { blobHash: blobRef.hash }
			}
		};
	}
};
//#endregion
exports.LumaRayVideoProvider = LumaRayVideoProvider;

//# sourceMappingURL=luma-ray-D6939Gtr.cjs.map