import { t as definePluginEntry } from "../../plugin-entry-CIpvZDX5.js";
import { t as createProviderApiKeyAuthMethod } from "../../provider-api-key-auth-CW0AyZpB.js";
import { m as ensureModelAllowlistEntry } from "../../provider-onboard-CzXRXTdJ.js";
import { A as REALTIME_VOICE_AUDIO_FORMAT_PCM16_24KHZ } from "../../session-runtime-CgKMATrj.js";
import "../../realtime-voice-1u13s2_d.js";
import "../../provider-auth-api-key-iRSRP2km.js";
import { n as buildDoubaoProvider, t as buildDoubaoCodingProvider } from "../../provider-catalog-C__dW0dV.js";
import { i as DOUBAO_MODEL_CATALOG, r as DOUBAO_CODING_MODEL_CATALOG } from "../../models-Cr5BnBpI.js";
import { n as applyVolcengineToolSchemaCompat } from "../../api-DlgyzeqR.js";
import { t as buildVolcengineSpeechProvider } from "../../speech-provider-fU4PfBRD.js";
import { randomUUID } from "node:crypto";
import WebSocket from "ws";
//#region extensions/volcengine/src/realtime-voice-provider.ts
const DEFAULT_VOLC_MODEL = "doubao-realtime";
const DEFAULT_VOLC_VOICE = "zh_female_qingxin";
const VOLCENGINE_REALTIME_URL = "wss://openspeech.bytedance.com/api/v1/realtime";
function trimToUndefined(v) {
	return v?.trim() || void 0;
}
function getApiKey(raw) {
	return trimToUndefined(raw.apiKey ?? raw.accessToken);
}
var VolcengineRealtimeVoiceBridge = class {
	constructor(req) {
		this.ws = null;
		this.closed = false;
		this.callbacks = {
			onAudio: req.onAudio,
			onClearAudio: req.onClearAudio,
			onMark: req.onMark,
			onTranscript: req.onTranscript,
			onEvent: req.onEvent,
			onToolCall: req.onToolCall,
			onReady: req.onReady,
			onError: req.onError,
			onClose: req.onClose
		};
		const raw = req.providerConfig ?? {};
		this.apiKey = getApiKey(raw) ?? "";
		this.appId = trimToUndefined(raw.appId) ?? "";
	}
	isConnected() {
		return this.ws?.readyState === WebSocket.OPEN;
	}
	async connect() {
		if (!this.apiKey) {
			const err = /* @__PURE__ */ new Error("Missing Volcengine API key for realtime voice.");
			this.callbacks.onError?.(err);
			throw err;
		}
		await new Promise((resolve, reject) => {
			const ws = new WebSocket(VOLCENGINE_REALTIME_URL);
			let opened = false;
			ws.on("open", () => {
				ws.send(JSON.stringify({
					type: "start_session",
					app_id: this.appId,
					token: this.apiKey,
					model: DEFAULT_VOLC_MODEL,
					voice: DEFAULT_VOLC_VOICE,
					audio_format: "pcm16_24k"
				}));
				opened = true;
				this.ws = ws;
				resolve();
				this.callbacks.onReady?.();
			});
			ws.on("error", (err) => {
				if (!opened) reject(err);
				this.callbacks.onError?.(err);
			});
			ws.on("close", () => {
				this.closed = true;
				if (!opened) reject(/* @__PURE__ */ new Error("WebSocket closed"));
				this.callbacks.onClose?.("error");
			});
			ws.on("message", (data) => {
				if (this.closed) return;
				try {
					const msg = JSON.parse(data.toString());
					switch (msg.type) {
						case "audio":
							if (msg.data) this.callbacks.onAudio(Buffer.from(msg.data, "base64"));
							break;
						case "audio_end":
							this.callbacks.onClearAudio();
							break;
						case "transcript":
							this.callbacks.onTranscript?.(msg.role ?? "assistant", msg.text ?? "", msg.is_final ?? false);
							break;
					}
				} catch {}
			});
		});
	}
	sendAudio(audio) {
		if (!this.ws || this.closed) return;
		this.ws.send(JSON.stringify({
			type: "audio",
			data: audio.toString("base64"),
			format: "pcm16",
			sample_rate: 24e3
		}));
	}
	setMediaTimestamp(_ts) {}
	submitToolResult(callId, result, _options) {
		if (!this.ws || this.closed) return;
		this.ws.send(JSON.stringify({
			type: "tool_result",
			call_id: callId,
			output: typeof result === "string" ? result : JSON.stringify(result)
		}));
	}
	handleBargeIn() {
		if (!this.ws || this.closed) return;
		this.ws.send(JSON.stringify({ type: "cancel" }));
	}
	acknowledgeMark() {}
	close() {
		this.closed = true;
		if (this.ws) {
			this.ws.close();
			this.ws = null;
		}
	}
};
function buildVolcengineRealtimeVoiceProvider() {
	return {
		id: "volcengine",
		label: "Volcengine (Doubao) Realtime Voice",
		defaultModel: DEFAULT_VOLC_MODEL,
		autoSelectOrder: 60,
		capabilities: {
			transports: ["gateway-relay"],
			inputAudioFormats: [REALTIME_VOICE_AUDIO_FORMAT_PCM16_24KHZ],
			outputAudioFormats: [REALTIME_VOICE_AUDIO_FORMAT_PCM16_24KHZ],
			supportsBrowserSession: true,
			supportsBargeIn: true,
			supportsToolCalls: false
		},
		resolveConfig: ({ rawConfig }) => rawConfig,
		isConfigured: ({ cfg, providerConfig }) => {
			if (getApiKey(providerConfig ?? {})) return true;
			const configKey = (cfg?.talk?.realtime?.providers)?.volcengine;
			return Boolean(trimToUndefined(configKey?.apiKey));
		},
		createBridge: (req) => new VolcengineRealtimeVoiceBridge(req),
		createBrowserSession: async (req) => {
			const raw = req.providerConfig ?? {};
			if (!getApiKey(raw)) throw new Error("Missing Volcengine API key for realtime voice browser session.");
			return {
				provider: "volcengine",
				transport: "gateway-relay",
				relaySessionId: randomUUID(),
				audio: {
					inputEncoding: "pcm16",
					inputSampleRateHz: 24e3,
					outputEncoding: "pcm16",
					outputSampleRateHz: 24e3
				},
				model: trimToUndefined(raw.model) ?? DEFAULT_VOLC_MODEL,
				voice: trimToUndefined(raw.voice) ?? DEFAULT_VOLC_VOICE
			};
		}
	};
}
//#endregion
//#region extensions/volcengine/index.ts
const PROVIDER_ID = "volcengine";
const VOLCENGINE_DEFAULT_MODEL_REF = "volcengine-plan/ark-code-latest";
var volcengine_default = definePluginEntry({
	id: PROVIDER_ID,
	name: "Volcengine Provider",
	description: "Bundled Volcengine provider plugin",
	register(api) {
		api.registerProvider({
			id: PROVIDER_ID,
			label: "Volcengine",
			docsPath: "/concepts/model-providers#volcano-engine-doubao",
			envVars: ["VOLCANO_ENGINE_API_KEY"],
			hookAliases: ["volcengine-plan"],
			auth: [createProviderApiKeyAuthMethod({
				providerId: PROVIDER_ID,
				methodId: "api-key",
				label: "Volcano Engine API key",
				hint: "API key",
				optionKey: "volcengineApiKey",
				flagName: "--volcengine-api-key",
				envVar: "VOLCANO_ENGINE_API_KEY",
				promptMessage: "Enter Volcano Engine API key",
				defaultModel: VOLCENGINE_DEFAULT_MODEL_REF,
				expectedProviders: ["volcengine"],
				applyConfig: (cfg) => ensureModelAllowlistEntry({
					cfg,
					modelRef: VOLCENGINE_DEFAULT_MODEL_REF
				}),
				wizard: {
					choiceId: "volcengine-api-key",
					choiceLabel: "Volcano Engine API key",
					groupId: "volcengine",
					groupLabel: "Volcano Engine",
					groupHint: "API key"
				}
			})],
			catalog: {
				order: "paired",
				run: async (ctx) => {
					const apiKey = ctx.resolveProviderApiKey(PROVIDER_ID).apiKey;
					if (!apiKey) return null;
					return { providers: {
						volcengine: {
							...buildDoubaoProvider(),
							apiKey
						},
						"volcengine-plan": {
							...buildDoubaoCodingProvider(),
							apiKey
						}
					} };
				}
			},
			augmentModelCatalog: () => {
				const volcengineModels = DOUBAO_MODEL_CATALOG.map((entry) => ({
					provider: "volcengine",
					id: entry.id,
					name: entry.name,
					reasoning: entry.reasoning,
					input: [...entry.input],
					contextWindow: entry.contextWindow
				}));
				const volcenginePlanModels = DOUBAO_CODING_MODEL_CATALOG.map((entry) => ({
					provider: "volcengine-plan",
					id: entry.id,
					name: entry.name,
					reasoning: entry.reasoning,
					input: [...entry.input],
					contextWindow: entry.contextWindow
				}));
				return [...volcengineModels, ...volcenginePlanModels];
			},
			normalizeResolvedModel: ({ model }) => applyVolcengineToolSchemaCompat(model)
		});
		api.registerSpeechProvider(buildVolcengineSpeechProvider());
		api.registerRealtimeVoiceProvider(buildVolcengineRealtimeVoiceProvider());
	}
});
//#endregion
export { volcengine_default as default };
