const require_helpers = require('./helpers.cjs');
const require_router = require('./router.cjs');
const require_sse_writer = require('./sse-writer.cjs');
const require_interruption = require('./interruption.cjs');
const require_chaos = require('./chaos.cjs');
const require_recorder = require('./recorder.cjs');

//#region src/cohere.ts
const ZERO_USAGE = {
	billed_units: {
		input_tokens: 0,
		output_tokens: 0,
		search_units: 0,
		classifications: 0
	},
	tokens: {
		input_tokens: 0,
		output_tokens: 0
	}
};
function cohereFinishReason(overrideFinishReason, defaultReason) {
	if (!overrideFinishReason) return defaultReason;
	if (overrideFinishReason === "stop") return "COMPLETE";
	if (overrideFinishReason === "tool_calls") return "TOOL_CALL";
	if (overrideFinishReason === "length") return "MAX_TOKENS";
	return overrideFinishReason;
}
function cohereUsage(overrides) {
	if (!overrides?.usage) return ZERO_USAGE;
	const inputTokens = overrides.usage.input_tokens ?? overrides.usage.prompt_tokens ?? 0;
	const outputTokens = overrides.usage.output_tokens ?? overrides.usage.completion_tokens ?? 0;
	return {
		billed_units: {
			input_tokens: inputTokens,
			output_tokens: outputTokens,
			search_units: 0,
			classifications: 0
		},
		tokens: {
			input_tokens: inputTokens,
			output_tokens: outputTokens
		}
	};
}
/** Extract plain text from structured content (array of { type, text } parts) or passthrough string. */
function extractTextContent(content) {
	if (typeof content === "string") return content;
	return content.filter((part) => part.type === "text" && part.text !== void 0).map((part) => part.text).join("");
}
/** Type guard: is this an OpenAI-style tool definition (has `function` key)? */
function isOpenAIToolDef(t) {
	return "function" in t && typeof t.function === "object";
}
function cohereToCompletionRequest(req) {
	const messages = [];
	for (const msg of req.messages) {
		const textContent = extractTextContent(msg.content);
		if (msg.role === "system") messages.push({
			role: "system",
			content: textContent
		});
		else if (msg.role === "user") messages.push({
			role: "user",
			content: textContent
		});
		else if (msg.role === "assistant") if (msg.tool_calls && msg.tool_calls.length > 0) messages.push({
			role: "assistant",
			content: textContent || null,
			tool_calls: msg.tool_calls.map((tc) => ({
				id: tc.id ?? require_helpers.generateToolCallId(),
				type: "function",
				function: {
					name: tc.function.name,
					arguments: tc.function.arguments
				}
			}))
		});
		else messages.push({
			role: "assistant",
			content: textContent
		});
		else if (msg.role === "tool") messages.push({
			role: "tool",
			content: textContent,
			tool_call_id: msg.tool_call_id
		});
	}
	let tools;
	if (req.tools && req.tools.length > 0) tools = req.tools.map((t) => {
		if (isOpenAIToolDef(t)) return {
			type: "function",
			function: {
				name: t.function.name,
				description: t.function.description,
				parameters: t.function.parameters
			}
		};
		return {
			type: "function",
			function: {
				name: t.name,
				description: t.description,
				parameters: t.parameter_definitions
			}
		};
	});
	return {
		model: req.model,
		messages,
		stream: req.stream,
		tools,
		...req.response_format && { response_format: req.response_format },
		...req.temperature !== void 0 && { temperature: req.temperature },
		...req.max_tokens !== void 0 && { max_tokens: req.max_tokens }
	};
}
function buildCohereTextResponse(content, reasoning, overrides) {
	const contentBlocks = [];
	if (reasoning) contentBlocks.push({
		type: "text",
		text: reasoning
	});
	contentBlocks.push({
		type: "text",
		text: content
	});
	return {
		id: overrides?.id ?? require_helpers.generateMessageId(),
		finish_reason: cohereFinishReason(overrides?.finishReason, "COMPLETE"),
		message: {
			role: "assistant",
			content: contentBlocks,
			tool_calls: [],
			tool_plan: "",
			citations: []
		},
		usage: cohereUsage(overrides)
	};
}
function buildCohereToolCallResponse(toolCalls, logger, reasoning, overrides) {
	const cohereCalls = toolCalls.map((tc) => {
		let argsJson;
		try {
			JSON.parse(tc.arguments || "{}");
			argsJson = tc.arguments || "{}";
		} catch {
			logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
			argsJson = "{}";
		}
		return {
			id: tc.id || require_helpers.generateToolCallId(),
			type: "function",
			function: {
				name: tc.name,
				arguments: argsJson
			}
		};
	});
	const contentBlocks = [];
	if (reasoning) contentBlocks.push({
		type: "text",
		text: reasoning
	});
	return {
		id: overrides?.id ?? require_helpers.generateMessageId(),
		finish_reason: cohereFinishReason(overrides?.finishReason, "TOOL_CALL"),
		message: {
			role: "assistant",
			content: contentBlocks,
			tool_calls: cohereCalls,
			tool_plan: "",
			citations: []
		},
		usage: cohereUsage(overrides)
	};
}
function buildCohereContentWithToolCallsResponse(content, toolCalls, logger, reasoning, overrides, blocks) {
	const resolvedBlocks = blocks && blocks.length > 0 ? require_helpers.resolveFixtureBlocks(blocks) : void 0;
	const cohereCalls = (resolvedBlocks ? resolvedBlocks.filter((b) => b.type === "toolCall").map((b) => ({
		name: b.name,
		arguments: b.arguments,
		id: b.id
	})) : toolCalls).map((tc) => {
		let argsJson;
		try {
			JSON.parse(tc.arguments || "{}");
			argsJson = tc.arguments || "{}";
		} catch {
			logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
			argsJson = "{}";
		}
		return {
			id: tc.id || require_helpers.generateToolCallId(),
			type: "function",
			function: {
				name: tc.name,
				arguments: argsJson
			}
		};
	});
	const textBlocks = resolvedBlocks?.filter((b) => b.type === "text");
	const hasTextEntry = resolvedBlocks ? (textBlocks?.length ?? 0) > 0 : true;
	const effectiveContent = resolvedBlocks ? (textBlocks ?? []).map((b) => b.text).join("") : content;
	const contentBlocks = [];
	if (reasoning) contentBlocks.push({
		type: "text",
		text: reasoning
	});
	if (hasTextEntry) contentBlocks.push({
		type: "text",
		text: effectiveContent
	});
	return {
		id: overrides?.id ?? require_helpers.generateMessageId(),
		finish_reason: cohereFinishReason(overrides?.finishReason, "TOOL_CALL"),
		message: {
			role: "assistant",
			content: contentBlocks,
			tool_calls: cohereCalls,
			tool_plan: "",
			citations: []
		},
		usage: cohereUsage(overrides)
	};
}
function buildCohereTextStreamEvents(content, chunkSize, reasoning, overrides) {
	const msgId = overrides?.id ?? require_helpers.generateMessageId();
	const events = [];
	events.push({
		id: msgId,
		type: "message-start",
		delta: { message: {
			role: "assistant",
			content: [],
			tool_plan: "",
			tool_calls: [],
			citations: []
		} }
	});
	let contentIndex = 0;
	if (reasoning) {
		events.push({
			type: "content-start",
			index: contentIndex,
			delta: { message: { content: { type: "text" } } }
		});
		for (let i = 0; i < reasoning.length; i += chunkSize) {
			const slice = reasoning.slice(i, i + chunkSize);
			events.push({
				type: "content-delta",
				index: contentIndex,
				delta: { message: { content: {
					type: "text",
					text: slice
				} } }
			});
		}
		events.push({
			type: "content-end",
			index: contentIndex
		});
		contentIndex++;
	}
	events.push({
		type: "content-start",
		index: contentIndex,
		delta: { message: { content: { type: "text" } } }
	});
	for (let i = 0; i < content.length; i += chunkSize) {
		const slice = content.slice(i, i + chunkSize);
		events.push({
			type: "content-delta",
			index: contentIndex,
			delta: { message: { content: {
				type: "text",
				text: slice
			} } }
		});
	}
	events.push({
		type: "content-end",
		index: contentIndex
	});
	events.push({
		type: "message-end",
		delta: {
			finish_reason: cohereFinishReason(overrides?.finishReason, "COMPLETE"),
			usage: cohereUsage(overrides)
		}
	});
	return events;
}
function buildCohereToolCallStreamEvents(toolCalls, chunkSize, logger, reasoning, overrides) {
	const msgId = overrides?.id ?? require_helpers.generateMessageId();
	const events = [];
	events.push({
		id: msgId,
		type: "message-start",
		delta: { message: {
			role: "assistant",
			content: [],
			tool_plan: "",
			tool_calls: [],
			citations: []
		} }
	});
	if (reasoning) {
		events.push({
			type: "content-start",
			index: 0,
			delta: { message: { content: { type: "text" } } }
		});
		for (let i = 0; i < reasoning.length; i += chunkSize) {
			const slice = reasoning.slice(i, i + chunkSize);
			events.push({
				type: "content-delta",
				index: 0,
				delta: { message: { content: {
					type: "text",
					text: slice
				} } }
			});
		}
		events.push({
			type: "content-end",
			index: 0
		});
	}
	events.push({
		type: "tool-plan-delta",
		delta: { message: { tool_plan: "I will use the requested tool." } }
	});
	for (let idx = 0; idx < toolCalls.length; idx++) {
		const tc = toolCalls[idx];
		const callId = tc.id || require_helpers.generateToolCallId();
		let argsJson;
		try {
			JSON.parse(tc.arguments || "{}");
			argsJson = tc.arguments || "{}";
		} catch {
			logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
			argsJson = "{}";
		}
		events.push({
			type: "tool-call-start",
			index: idx,
			delta: { message: { tool_calls: {
				id: callId,
				type: "function",
				function: {
					name: tc.name,
					arguments: ""
				}
			} } }
		});
		for (let i = 0; i < argsJson.length; i += chunkSize) {
			const slice = argsJson.slice(i, i + chunkSize);
			events.push({
				type: "tool-call-delta",
				index: idx,
				delta: { message: { tool_calls: { function: { arguments: slice } } } }
			});
		}
		events.push({
			type: "tool-call-end",
			index: idx
		});
	}
	events.push({
		type: "message-end",
		delta: {
			finish_reason: cohereFinishReason(overrides?.finishReason, "TOOL_CALL"),
			usage: cohereUsage(overrides)
		}
	});
	return events;
}
function buildCohereContentWithToolCallsStreamEvents(content, toolCalls, chunkSize, logger, reasoning, overrides, blocks) {
	const msgId = overrides?.id ?? require_helpers.generateMessageId();
	const events = [];
	events.push({
		id: msgId,
		type: "message-start",
		delta: { message: {
			role: "assistant",
			content: [],
			tool_plan: "",
			tool_calls: [],
			citations: []
		} }
	});
	let contentIndex = 0;
	if (reasoning) {
		events.push({
			type: "content-start",
			index: contentIndex,
			delta: { message: { content: { type: "text" } } }
		});
		for (let i = 0; i < reasoning.length; i += chunkSize) {
			const slice = reasoning.slice(i, i + chunkSize);
			events.push({
				type: "content-delta",
				index: contentIndex,
				delta: { message: { content: {
					type: "text",
					text: slice
				} } }
			});
		}
		events.push({
			type: "content-end",
			index: contentIndex
		});
		contentIndex++;
	}
	if (blocks && blocks.length > 0) {
		const resolved = require_helpers.resolveFixtureBlocks(blocks);
		let toolPlanEmitted = false;
		let toolIdx = 0;
		resolved.forEach((block) => {
			if (block.type === "toolCall") {
				if (!toolPlanEmitted) {
					events.push({
						type: "tool-plan-delta",
						delta: { message: { tool_plan: "I will use the requested tool." } }
					});
					toolPlanEmitted = true;
				}
				const callId = block.id || require_helpers.generateToolCallId();
				let argsJson;
				try {
					JSON.parse(block.arguments || "{}");
					argsJson = block.arguments || "{}";
				} catch {
					logger.warn(`Malformed JSON in fixture tool call arguments for "${block.name}": ${block.arguments}`);
					argsJson = "{}";
				}
				events.push({
					type: "tool-call-start",
					index: toolIdx,
					delta: { message: { tool_calls: {
						id: callId,
						type: "function",
						function: {
							name: block.name,
							arguments: ""
						}
					} } }
				});
				for (let i = 0; i < argsJson.length; i += chunkSize) events.push({
					type: "tool-call-delta",
					index: toolIdx,
					delta: { message: { tool_calls: { function: { arguments: argsJson.slice(i, i + chunkSize) } } } }
				});
				events.push({
					type: "tool-call-end",
					index: toolIdx
				});
				toolIdx++;
			} else {
				events.push({
					type: "content-start",
					index: contentIndex,
					delta: { message: { content: { type: "text" } } }
				});
				for (let i = 0; i < block.text.length; i += chunkSize) events.push({
					type: "content-delta",
					index: contentIndex,
					delta: { message: { content: {
						type: "text",
						text: block.text.slice(i, i + chunkSize)
					} } }
				});
				events.push({
					type: "content-end",
					index: contentIndex
				});
				contentIndex++;
			}
		});
		events.push({
			type: "message-end",
			delta: {
				finish_reason: cohereFinishReason(overrides?.finishReason, "TOOL_CALL"),
				usage: cohereUsage(overrides)
			}
		});
		return events;
	}
	events.push({
		type: "content-start",
		index: contentIndex,
		delta: { message: { content: { type: "text" } } }
	});
	for (let i = 0; i < content.length; i += chunkSize) {
		const slice = content.slice(i, i + chunkSize);
		events.push({
			type: "content-delta",
			index: contentIndex,
			delta: { message: { content: {
				type: "text",
				text: slice
			} } }
		});
	}
	events.push({
		type: "content-end",
		index: contentIndex
	});
	events.push({
		type: "tool-plan-delta",
		delta: { message: { tool_plan: "I will use the requested tool." } }
	});
	for (let idx = 0; idx < toolCalls.length; idx++) {
		const tc = toolCalls[idx];
		const callId = tc.id || require_helpers.generateToolCallId();
		let argsJson;
		try {
			JSON.parse(tc.arguments || "{}");
			argsJson = tc.arguments || "{}";
		} catch {
			logger.warn(`Malformed JSON in fixture tool call arguments for "${tc.name}": ${tc.arguments}`);
			argsJson = "{}";
		}
		events.push({
			type: "tool-call-start",
			index: idx,
			delta: { message: { tool_calls: {
				id: callId,
				type: "function",
				function: {
					name: tc.name,
					arguments: ""
				}
			} } }
		});
		for (let i = 0; i < argsJson.length; i += chunkSize) {
			const slice = argsJson.slice(i, i + chunkSize);
			events.push({
				type: "tool-call-delta",
				index: idx,
				delta: { message: { tool_calls: { function: { arguments: slice } } } }
			});
		}
		events.push({
			type: "tool-call-end",
			index: idx
		});
	}
	events.push({
		type: "message-end",
		delta: {
			finish_reason: cohereFinishReason(overrides?.finishReason, "TOOL_CALL"),
			usage: cohereUsage(overrides)
		}
	});
	return events;
}
async function writeCohereSSEStream(res, events, optionsOrLatency) {
	const opts = typeof optionsOrLatency === "number" ? { latency: optionsOrLatency } : optionsOrLatency ?? {};
	const latency = opts.latency ?? 0;
	const profile = opts.streamingProfile;
	const { recordedTimings, replaySpeed } = opts;
	const signal = opts.signal;
	const onChunkSent = opts.onChunkSent;
	if (res.writableEnded) return true;
	res.setHeader("Content-Type", "text/event-stream");
	res.setHeader("Cache-Control", "no-cache");
	res.setHeader("Connection", "keep-alive");
	let chunkIndex = 0;
	for (const event of events) {
		const chunkDelay = require_sse_writer.calculateDelay(chunkIndex, profile, latency, recordedTimings, replaySpeed);
		if (chunkDelay > 0) await require_sse_writer.delay(chunkDelay, signal);
		if (signal?.aborted) return false;
		if (res.writableEnded) return true;
		res.write(`event: ${event.type}\ndata: ${JSON.stringify(event)}\n\n`);
		onChunkSent?.();
		if (signal?.aborted) return false;
		chunkIndex++;
	}
	if (!res.writableEnded) res.end();
	return true;
}
async function handleCohere(req, res, raw, fixtures, journal, defaults, setCorsHeaders) {
	const { logger } = defaults;
	setCorsHeaders(res);
	let cohereReq;
	try {
		cohereReq = JSON.parse(raw);
	} catch (parseErr) {
		const detail = parseErr instanceof Error ? parseErr.message : "unknown";
		journal.add({
			method: req.method ?? "POST",
			path: req.url ?? "/v2/chat",
			headers: require_helpers.flattenHeaders(req.headers),
			body: null,
			response: {
				status: 400,
				fixture: null
			}
		});
		require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
			message: `Malformed JSON body: ${detail}`,
			type: "invalid_request_error"
		} }));
		return;
	}
	if (!cohereReq.model) {
		journal.add({
			method: req.method ?? "POST",
			path: req.url ?? "/v2/chat",
			headers: require_helpers.flattenHeaders(req.headers),
			body: null,
			response: {
				status: 400,
				fixture: null
			}
		});
		require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
			message: "model is required",
			type: "invalid_request_error"
		} }));
		return;
	}
	if (!cohereReq.messages || !Array.isArray(cohereReq.messages)) {
		journal.add({
			method: req.method ?? "POST",
			path: req.url ?? "/v2/chat",
			headers: require_helpers.flattenHeaders(req.headers),
			body: null,
			response: {
				status: 400,
				fixture: null
			}
		});
		require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
			message: "Invalid request: messages array is required",
			type: "invalid_request_error"
		} }));
		return;
	}
	const completionReq = cohereToCompletionRequest(cohereReq);
	completionReq._endpointType = "chat";
	completionReq._context = require_helpers.getContext(req);
	const testId = require_helpers.getTestId(req);
	const { fixture, skippedBySequenceOrTurn } = require_router.matchFixtureDiagnostic(fixtures, completionReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform, require_router.recordMatchOptions(!!defaults.record, defaults.logger));
	if (fixture) {
		journal.incrementFixtureMatchCount(fixture, fixtures, testId);
		logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);
	} else logger.debug(`No fixture matched for request`);
	if (require_chaos.applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
		method: req.method ?? "POST",
		path: req.url ?? "/v2/chat",
		headers: require_helpers.flattenHeaders(req.headers),
		body: completionReq
	}, fixture ? "fixture" : "proxy", defaults.registry, defaults.logger)) return;
	if (!fixture) {
		if (require_helpers.resolveStrictMode(defaults.strict, req.headers)) {
			const strictStatus = 503;
			const strictMessage = require_helpers.strictNoMatchMessage(skippedBySequenceOrTurn);
			logger.error(require_helpers.strictNoMatchLogLine(req.method ?? "POST", req.url ?? "/v2/chat", skippedBySequenceOrTurn));
			journal.add({
				method: req.method ?? "POST",
				path: req.url ?? "/v2/chat",
				headers: require_helpers.flattenHeaders(req.headers),
				body: completionReq,
				response: {
					status: strictStatus,
					fixture: null,
					...require_helpers.strictOverrideField(defaults.strict, req.headers)
				}
			});
			require_sse_writer.writeErrorResponse(res, strictStatus, JSON.stringify({ error: {
				message: strictMessage,
				type: "invalid_request_error"
			} }));
			return;
		}
		if (defaults.record) {
			const outcome = await require_recorder.proxyAndRecord(req, res, completionReq, "cohere", req.url ?? "/v2/chat", fixtures, defaults, raw);
			if (outcome === "handled_by_hook") return;
			if (outcome !== "not_configured") {
				journal.add({
					method: req.method ?? "POST",
					path: req.url ?? "/v2/chat",
					headers: require_helpers.flattenHeaders(req.headers),
					body: completionReq,
					response: {
						status: res.statusCode ?? 200,
						fixture: null,
						source: "proxy"
					}
				});
				return;
			}
		}
		journal.add({
			method: req.method ?? "POST",
			path: req.url ?? "/v2/chat",
			headers: require_helpers.flattenHeaders(req.headers),
			body: completionReq,
			response: {
				status: 404,
				fixture: null,
				...require_helpers.strictOverrideField(defaults.strict, req.headers)
			}
		});
		require_sse_writer.writeErrorResponse(res, 404, JSON.stringify({ error: {
			message: "No fixture matched",
			type: "invalid_request_error"
		} }));
		return;
	}
	const response = await require_helpers.resolveResponse(fixture, completionReq);
	const latency = fixture.latency ?? defaults.latency;
	const chunkSize = Math.max(1, fixture.chunkSize ?? defaults.chunkSize);
	if (require_helpers.isErrorResponse(response)) {
		const status = response.status ?? 500;
		journal.add({
			method: req.method ?? "POST",
			path: req.url ?? "/v2/chat",
			headers: require_helpers.flattenHeaders(req.headers),
			body: completionReq,
			response: {
				status,
				fixture
			}
		});
		require_sse_writer.writeErrorResponse(res, status, require_helpers.serializeErrorResponse(response), { retryAfter: response.retryAfter });
		return;
	}
	if (require_helpers.isContentWithToolCallsResponse(response)) {
		if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Cohere v2 Chat API — ignoring");
		const overrides = require_helpers.extractOverrides(response);
		const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
		const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, cohereReq.model, effectiveStrict, logger);
		const journalEntry = journal.add({
			method: req.method ?? "POST",
			path: req.url ?? "/v2/chat",
			headers: require_helpers.flattenHeaders(req.headers),
			body: completionReq,
			response: {
				status: 200,
				fixture
			}
		});
		if (cohereReq.stream !== true) {
			const body = buildCohereContentWithToolCallsResponse(response.content ?? "", response.toolCalls ?? [], logger, effReasoning, overrides, response.blocks);
			res.writeHead(200, { "Content-Type": "application/json" });
			res.end(JSON.stringify(body));
		} else {
			const events = buildCohereContentWithToolCallsStreamEvents(response.content ?? "", response.toolCalls ?? [], chunkSize, logger, effReasoning, overrides, response.blocks);
			const interruption = require_interruption.createInterruptionSignal(fixture);
			if (!await writeCohereSSEStream(res, events, {
				latency,
				streamingProfile: fixture.streamingProfile,
				recordedTimings: fixture.recordedTimings,
				replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
				signal: interruption?.signal,
				onChunkSent: interruption?.tick
			})) {
				if (!res.writableEnded) res.destroy();
				journalEntry.response.interrupted = true;
				journalEntry.response.interruptReason = interruption?.reason();
			}
			interruption?.cleanup();
		}
		return;
	}
	if (require_helpers.isTextResponse(response)) {
		if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Cohere v2 Chat API — ignoring");
		const overrides = require_helpers.extractOverrides(response);
		const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
		const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, cohereReq.model, effectiveStrict, logger);
		const journalEntry = journal.add({
			method: req.method ?? "POST",
			path: req.url ?? "/v2/chat",
			headers: require_helpers.flattenHeaders(req.headers),
			body: completionReq,
			response: {
				status: 200,
				fixture
			}
		});
		if (cohereReq.stream !== true) {
			const body = buildCohereTextResponse(response.content, effReasoning, overrides);
			res.writeHead(200, { "Content-Type": "application/json" });
			res.end(JSON.stringify(body));
		} else {
			const events = buildCohereTextStreamEvents(response.content, chunkSize, effReasoning, overrides);
			const interruption = require_interruption.createInterruptionSignal(fixture);
			if (!await writeCohereSSEStream(res, events, {
				latency,
				streamingProfile: fixture.streamingProfile,
				recordedTimings: fixture.recordedTimings,
				replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
				signal: interruption?.signal,
				onChunkSent: interruption?.tick
			})) {
				if (!res.writableEnded) res.destroy();
				journalEntry.response.interrupted = true;
				journalEntry.response.interruptReason = interruption?.reason();
			}
			interruption?.cleanup();
		}
		return;
	}
	if (require_helpers.isToolCallResponse(response)) {
		if (response.webSearches?.length) logger.warn("webSearches in fixture response are not supported for Cohere v2 Chat API — ignoring");
		const overrides = require_helpers.extractOverrides(response);
		const effectiveStrict = require_helpers.resolveStrictMode(defaults.strict, req.headers);
		const effReasoning = require_helpers.resolveReasoningForModel(response.reasoning, cohereReq.model, effectiveStrict, logger);
		const journalEntry = journal.add({
			method: req.method ?? "POST",
			path: req.url ?? "/v2/chat",
			headers: require_helpers.flattenHeaders(req.headers),
			body: completionReq,
			response: {
				status: 200,
				fixture
			}
		});
		if (cohereReq.stream !== true) {
			const body = buildCohereToolCallResponse(response.toolCalls, logger, effReasoning, overrides);
			res.writeHead(200, { "Content-Type": "application/json" });
			res.end(JSON.stringify(body));
		} else {
			const events = buildCohereToolCallStreamEvents(response.toolCalls, chunkSize, logger, effReasoning, overrides);
			const interruption = require_interruption.createInterruptionSignal(fixture);
			if (!await writeCohereSSEStream(res, events, {
				latency,
				streamingProfile: fixture.streamingProfile,
				recordedTimings: fixture.recordedTimings,
				replaySpeed: fixture.replaySpeed ?? defaults.replaySpeed,
				signal: interruption?.signal,
				onChunkSent: interruption?.tick
			})) {
				if (!res.writableEnded) res.destroy();
				journalEntry.response.interrupted = true;
				journalEntry.response.interruptReason = interruption?.reason();
			}
			interruption?.cleanup();
		}
		return;
	}
	journal.add({
		method: req.method ?? "POST",
		path: req.url ?? "/v2/chat",
		headers: require_helpers.flattenHeaders(req.headers),
		body: completionReq,
		response: {
			status: 500,
			fixture
		}
	});
	require_sse_writer.writeErrorResponse(res, 500, JSON.stringify({ error: {
		message: "Fixture response did not match any known type",
		type: "server_error"
	} }));
}
async function handleCohereEmbed(req, res, raw, fixtures, journal, defaults, setCorsHeaders) {
	const { logger } = defaults;
	setCorsHeaders(res);
	let embedReq;
	try {
		embedReq = JSON.parse(raw);
	} catch (parseErr) {
		const detail = parseErr instanceof Error ? parseErr.message : "unknown";
		journal.add({
			method: req.method ?? "POST",
			path: req.url ?? "/v2/embed",
			headers: require_helpers.flattenHeaders(req.headers),
			body: null,
			response: {
				status: 400,
				fixture: null
			}
		});
		require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
			message: `Malformed JSON body: ${detail}`,
			type: "invalid_request_error"
		} }));
		return;
	}
	if (!embedReq.model) {
		journal.add({
			method: req.method ?? "POST",
			path: req.url ?? "/v2/embed",
			headers: require_helpers.flattenHeaders(req.headers),
			body: null,
			response: {
				status: 400,
				fixture: null
			}
		});
		require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
			message: "model is required",
			type: "invalid_request_error"
		} }));
		return;
	}
	if (!embedReq.texts || !Array.isArray(embedReq.texts)) {
		journal.add({
			method: req.method ?? "POST",
			path: req.url ?? "/v2/embed",
			headers: require_helpers.flattenHeaders(req.headers),
			body: null,
			response: {
				status: 400,
				fixture: null
			}
		});
		require_sse_writer.writeErrorResponse(res, 400, JSON.stringify({ error: {
			message: "Invalid request: texts array is required",
			type: "invalid_request_error"
		} }));
		return;
	}
	const combinedInput = embedReq.texts.join(" ");
	const syntheticReq = {
		model: embedReq.model,
		messages: [],
		embeddingInput: combinedInput,
		_endpointType: "embedding",
		_context: require_helpers.getContext(req)
	};
	const testId = require_helpers.getTestId(req);
	const { fixture, skippedBySequenceOrTurn } = require_router.matchFixtureDiagnostic(fixtures, syntheticReq, journal.getFixtureMatchCountsForTest(testId), defaults.requestTransform, require_router.recordMatchOptions(!!defaults.record, defaults.logger));
	if (fixture) {
		journal.incrementFixtureMatchCount(fixture, fixtures, testId);
		logger.debug(`Fixture matched: ${JSON.stringify(fixture.match).slice(0, 120)}`);
	} else logger.debug(`No fixture matched for request`);
	if (require_chaos.applyChaos(res, fixture, defaults.chaos, req.headers, journal, {
		method: req.method ?? "POST",
		path: req.url ?? "/v2/embed",
		headers: require_helpers.flattenHeaders(req.headers),
		body: syntheticReq
	}, fixture ? "fixture" : "proxy", defaults.registry, defaults.logger)) return;
	const embeddingTypes = embedReq.embedding_types && embedReq.embedding_types.length > 0 ? embedReq.embedding_types : ["float"];
	if (fixture) {
		const response = await require_helpers.resolveResponse(fixture, syntheticReq);
		if (require_helpers.isErrorResponse(response)) {
			const status = response.status ?? 500;
			journal.add({
				method: req.method ?? "POST",
				path: req.url ?? "/v2/embed",
				headers: require_helpers.flattenHeaders(req.headers),
				body: syntheticReq,
				response: {
					status,
					fixture
				}
			});
			require_sse_writer.writeErrorResponse(res, status, require_helpers.serializeErrorResponse(response), { retryAfter: response.retryAfter });
			return;
		}
		if (require_helpers.isEmbeddingResponse(response)) {
			journal.add({
				method: req.method ?? "POST",
				path: req.url ?? "/v2/embed",
				headers: require_helpers.flattenHeaders(req.headers),
				body: syntheticReq,
				response: {
					status: 200,
					fixture
				}
			});
			const vectors = embedReq.texts.map(() => [...response.embedding]);
			const embeddings = {};
			for (const t of embeddingTypes) embeddings[t] = vectors;
			const body = {
				id: require_helpers.generateMessageId(),
				texts: embedReq.texts,
				embeddings,
				meta: { api_version: { version: "2" } }
			};
			res.writeHead(200, { "Content-Type": "application/json" });
			res.end(JSON.stringify(body));
			return;
		}
		journal.add({
			method: req.method ?? "POST",
			path: req.url ?? "/v2/embed",
			headers: require_helpers.flattenHeaders(req.headers),
			body: syntheticReq,
			response: {
				status: 500,
				fixture
			}
		});
		require_sse_writer.writeErrorResponse(res, 500, JSON.stringify({ error: {
			message: "Fixture response did not match any known embedding type (must have embedding or error)",
			type: "server_error"
		} }));
		return;
	}
	if (require_helpers.resolveStrictMode(defaults.strict, req.headers)) {
		const strictMessage = require_helpers.strictNoMatchMessage(skippedBySequenceOrTurn);
		logger.error(require_helpers.strictNoMatchLogLine(req.method ?? "POST", req.url ?? "/v2/embed", skippedBySequenceOrTurn));
		journal.add({
			method: req.method ?? "POST",
			path: req.url ?? "/v2/embed",
			headers: require_helpers.flattenHeaders(req.headers),
			body: syntheticReq,
			response: {
				status: 503,
				fixture: null,
				...require_helpers.strictOverrideField(defaults.strict, req.headers)
			}
		});
		require_sse_writer.writeErrorResponse(res, 503, JSON.stringify({ error: {
			message: strictMessage,
			type: "invalid_request_error"
		} }));
		return;
	}
	if (defaults.record) {
		const outcome = await require_recorder.proxyAndRecord(req, res, syntheticReq, "cohere", req.url ?? "/v2/embed", fixtures, defaults, raw);
		if (outcome === "handled_by_hook") return;
		if (outcome !== "not_configured") {
			journal.add({
				method: req.method ?? "POST",
				path: req.url ?? "/v2/embed",
				headers: require_helpers.flattenHeaders(req.headers),
				body: syntheticReq,
				response: {
					status: res.statusCode ?? 200,
					fixture: null,
					source: "proxy"
				}
			});
			return;
		}
	}
	logger.warn(`No embedding fixture matched for "${combinedInput.slice(0, 80)}" — returning deterministic fallback`);
	const dimensions = 1024;
	const vectors = embedReq.texts.map((text) => require_helpers.generateDeterministicEmbedding(text, dimensions));
	const embeddings = {};
	for (const t of embeddingTypes) embeddings[t] = vectors;
	journal.add({
		method: req.method ?? "POST",
		path: req.url ?? "/v2/embed",
		headers: require_helpers.flattenHeaders(req.headers),
		body: syntheticReq,
		response: {
			status: 200,
			fixture: null
		}
	});
	const body = {
		id: require_helpers.generateMessageId(),
		texts: embedReq.texts,
		embeddings,
		meta: { api_version: { version: "2" } }
	};
	res.writeHead(200, { "Content-Type": "application/json" });
	res.end(JSON.stringify(body));
}

//#endregion
exports.cohereToCompletionRequest = cohereToCompletionRequest;
exports.handleCohere = handleCohere;
exports.handleCohereEmbed = handleCohereEmbed;
//# sourceMappingURL=cohere.cjs.map