import { createLogger } from "../utils/logger/index.js";
import { init_logger } from "../utils/logger.js";
import { listProvidersForCapability } from "./registry.js";
//#region src/media-understanding/runner.ts
init_logger();
const log = createLogger("MediaUnderstandingRunner");
const KIND_BY_CAPABILITY = {
	audio: "audio.transcription",
	image: "image.description",
	video: "video.description"
};
function orderProviders(providers, capability, override) {
	if (override && override.length > 0) {
		const lookup = new Map(providers.map((p) => [p.id.toLowerCase(), p]));
		const ordered = [];
		const used = /* @__PURE__ */ new Set();
		for (const id of override) {
			const provider = lookup.get(id.toLowerCase());
			if (provider && !used.has(provider.id)) {
				ordered.push(provider);
				used.add(provider.id);
			}
		}
		for (const provider of providers) if (!used.has(provider.id)) ordered.push(provider);
		return ordered;
	}
	return [...providers].sort((a, b) => {
		return (a.autoPriority?.[capability] ?? Number.MAX_SAFE_INTEGER) - (b.autoPriority?.[capability] ?? Number.MAX_SAFE_INTEGER);
	});
}
function pickMethod(provider, capability) {
	if (capability === "audio") return provider.transcribeAudio;
	if (capability === "image") return provider.describeImage;
	return provider.describeVideo;
}
async function runCapability(options) {
	const eligibleProviders = listProvidersForCapability(options.capability);
	if (eligibleProviders.length === 0) {
		log.debug({ capability: options.capability }, `No providers registered for capability "${options.capability}"`);
		return {
			decision: {
				capability: options.capability,
				outcome: "disabled",
				attachments: options.attachments.map((a) => ({
					attachmentIndex: a.attachmentIndex,
					attempts: []
				}))
			},
			outputs: []
		};
	}
	if (options.attachments.length === 0) return {
		decision: {
			capability: options.capability,
			outcome: "no-attachment",
			attachments: []
		},
		outputs: []
	};
	const providers = orderProviders(eligibleProviders, options.capability, options.providerOrder);
	const attachmentDecisions = [];
	const outputs = [];
	for (const attachment of options.attachments) {
		options.signal?.throwIfAborted();
		const attempts = [];
		let chosen;
		for (const provider of providers) {
			const method = pickMethod(provider, options.capability);
			if (!method) {
				attempts.push({
					provider: provider.id,
					type: "provider",
					outcome: "skipped",
					reason: `provider "${provider.id}" missing method for capability "${options.capability}"`
				});
				continue;
			}
			const request = options.buildRequest({
				provider,
				attachment
			});
			if (!request) {
				attempts.push({
					provider: provider.id,
					type: "provider",
					outcome: "skipped",
					reason: "caller buildRequest returned undefined (likely missing config)"
				});
				continue;
			}
			try {
				const callResult = await method(request);
				const text = callResult.text?.trim() ?? "";
				if (!text) {
					attempts.push({
						provider: provider.id,
						type: "provider",
						outcome: "failed",
						reason: "empty transcription/description text",
						model: callResult.model
					});
					continue;
				}
				chosen = {
					provider: provider.id,
					type: "provider",
					outcome: "success",
					model: callResult.model
				};
				attempts.push(chosen);
				outputs.push({
					kind: KIND_BY_CAPABILITY[options.capability],
					attachmentIndex: attachment.attachmentIndex,
					text,
					provider: provider.id,
					model: callResult.model
				});
				break;
			} catch (error) {
				const reason = error instanceof Error ? error.message : String(error);
				log.warn({
					err: error,
					providerId: provider.id,
					capability: options.capability,
					attachmentIndex: attachment.attachmentIndex
				}, `Provider "${provider.id}" failed for ${options.capability}: ${reason}`);
				attempts.push({
					provider: provider.id,
					type: "provider",
					outcome: "failed",
					reason
				});
			}
		}
		attachmentDecisions.push({
			attachmentIndex: attachment.attachmentIndex,
			attempts,
			...chosen ? { chosen } : {}
		});
	}
	const overallOutcome = attachmentDecisions.every((d) => d.chosen) ? "success" : attachmentDecisions.some((d) => d.chosen) ? "success" : "failed";
	return {
		decision: {
			capability: options.capability,
			outcome: overallOutcome,
			attachments: attachmentDecisions
		},
		outputs
	};
}
//#endregion
export { runCapability };

//# sourceMappingURL=runner.js.map