import { At as isRecord } from "./entry.js";
import { b as ensureAuthProfileStore, h as listProfilesForProvider } from "./auth-profiles-D11Xw15i.js";
import { t as resolveSymiAgentDir } from "./agent-paths-DryQawbH.js";
import { i as loadConfig } from "./config-D7TcU4qN.js";
import { a as resolveAwsSdkEnvVarName, o as resolveEnvApiKey } from "./model-auth-Byr7Gic_.js";
import { r as resolveCopilotApiToken, t as DEFAULT_COPILOT_API_BASE_URL } from "./github-copilot-token-B5y4__YM.js";
import path from "node:path";
import fs from "node:fs/promises";
import { randomUUID } from "node:crypto";
import { createAssistantMessageEventStream } from "@mariozechner/pi-ai";
import { BedrockClient, ListFoundationModelsCommand } from "@aws-sdk/client-bedrock";

//#region src/agents/bedrock-discovery.ts
const DEFAULT_REFRESH_INTERVAL_SECONDS = 3600;
const DEFAULT_CONTEXT_WINDOW = 32e3;
const DEFAULT_MAX_TOKENS = 4096;
const DEFAULT_COST = {
	input: 0,
	output: 0,
	cacheRead: 0,
	cacheWrite: 0
};
const discoveryCache = /* @__PURE__ */ new Map();
let hasLoggedBedrockError = false;
function normalizeProviderFilter(filter) {
	if (!filter || filter.length === 0) return [];
	const normalized = new Set(filter.map((entry) => entry.trim().toLowerCase()).filter((entry) => entry.length > 0));
	return Array.from(normalized).toSorted();
}
function buildCacheKey(params) {
	return JSON.stringify(params);
}
function includesTextModalities(modalities) {
	return (modalities ?? []).some((entry) => entry.toLowerCase() === "text");
}
function isActive(summary) {
	const status = summary.modelLifecycle?.status;
	return typeof status === "string" ? status.toUpperCase() === "ACTIVE" : false;
}
function mapInputModalities(summary) {
	const inputs = summary.inputModalities ?? [];
	const mapped = /* @__PURE__ */ new Set();
	for (const modality of inputs) {
		const lower = modality.toLowerCase();
		if (lower === "text") mapped.add("text");
		if (lower === "image") mapped.add("image");
	}
	if (mapped.size === 0) mapped.add("text");
	return Array.from(mapped);
}
function inferReasoningSupport(summary) {
	const haystack = `${summary.modelId ?? ""} ${summary.modelName ?? ""}`.toLowerCase();
	return haystack.includes("reasoning") || haystack.includes("thinking");
}
function resolveDefaultContextWindow(config) {
	const value = Math.floor(config?.defaultContextWindow ?? DEFAULT_CONTEXT_WINDOW);
	return value > 0 ? value : DEFAULT_CONTEXT_WINDOW;
}
function resolveDefaultMaxTokens(config) {
	const value = Math.floor(config?.defaultMaxTokens ?? DEFAULT_MAX_TOKENS);
	return value > 0 ? value : DEFAULT_MAX_TOKENS;
}
function matchesProviderFilter(summary, filter) {
	if (filter.length === 0) return true;
	const normalized = (summary.providerName ?? (typeof summary.modelId === "string" ? summary.modelId.split(".")[0] : void 0))?.trim().toLowerCase();
	if (!normalized) return false;
	return filter.includes(normalized);
}
function shouldIncludeSummary(summary, filter) {
	if (!summary.modelId?.trim()) return false;
	if (!matchesProviderFilter(summary, filter)) return false;
	if (summary.responseStreamingSupported !== true) return false;
	if (!includesTextModalities(summary.outputModalities)) return false;
	if (!isActive(summary)) return false;
	return true;
}
function toModelDefinition(summary, defaults) {
	const id = summary.modelId?.trim() ?? "";
	return {
		id,
		name: summary.modelName?.trim() || id,
		reasoning: inferReasoningSupport(summary),
		input: mapInputModalities(summary),
		cost: DEFAULT_COST,
		contextWindow: defaults.contextWindow,
		maxTokens: defaults.maxTokens
	};
}
async function discoverBedrockModels(params) {
	const refreshIntervalSeconds = Math.max(0, Math.floor(params.config?.refreshInterval ?? DEFAULT_REFRESH_INTERVAL_SECONDS));
	const providerFilter = normalizeProviderFilter(params.config?.providerFilter);
	const defaultContextWindow = resolveDefaultContextWindow(params.config);
	const defaultMaxTokens = resolveDefaultMaxTokens(params.config);
	const cacheKey = buildCacheKey({
		region: params.region,
		providerFilter,
		refreshIntervalSeconds,
		defaultContextWindow,
		defaultMaxTokens
	});
	const now = params.now?.() ?? Date.now();
	if (refreshIntervalSeconds > 0) {
		const cached = discoveryCache.get(cacheKey);
		if (cached?.value && cached.expiresAt > now) return cached.value;
		if (cached?.inFlight) return cached.inFlight;
	}
	const client = (params.clientFactory ?? ((region) => new BedrockClient({ region })))(params.region);
	const discoveryPromise = (async () => {
		const response = await client.send(new ListFoundationModelsCommand({}));
		const discovered = [];
		for (const summary of response.modelSummaries ?? []) {
			if (!shouldIncludeSummary(summary, providerFilter)) continue;
			discovered.push(toModelDefinition(summary, {
				contextWindow: defaultContextWindow,
				maxTokens: defaultMaxTokens
			}));
		}
		return discovered.toSorted((a, b) => a.name.localeCompare(b.name));
	})();
	if (refreshIntervalSeconds > 0) discoveryCache.set(cacheKey, {
		expiresAt: now + refreshIntervalSeconds * 1e3,
		inFlight: discoveryPromise
	});
	try {
		const value = await discoveryPromise;
		if (refreshIntervalSeconds > 0) discoveryCache.set(cacheKey, {
			expiresAt: now + refreshIntervalSeconds * 1e3,
			value
		});
		return value;
	} catch (error) {
		if (refreshIntervalSeconds > 0) discoveryCache.delete(cacheKey);
		if (!hasLoggedBedrockError) {
			hasLoggedBedrockError = true;
			console.warn(`[bedrock-discovery] Failed to list models: ${String(error)}`);
		}
		return [];
	}
}

//#endregion
//#region src/agents/byteplus-models.ts
const BYTEPLUS_BASE_URL = "https://ark.ap-southeast.bytepluses.com/api/v3";
const BYTEPLUS_CODING_BASE_URL = "https://ark.ap-southeast.bytepluses.com/api/coding/v3";
const BYTEPLUS_DEFAULT_MODEL_ID = "seed-1-8-251228";
const BYTEPLUS_DEFAULT_MODEL_REF = `byteplus/${BYTEPLUS_DEFAULT_MODEL_ID}`;
const BYTEPLUS_DEFAULT_COST = {
	input: 1e-4,
	output: 2e-4,
	cacheRead: 0,
	cacheWrite: 0
};
/**
* Complete catalog of BytePlus ARK models.
*
* BytePlus ARK provides access to various models
* through the ARK API. Authentication requires a BYTEPLUS_API_KEY.
*/
const BYTEPLUS_MODEL_CATALOG = [
	{
		id: "seed-1-8-251228",
		name: "Seed 1.8",
		reasoning: false,
		input: ["text", "image"],
		contextWindow: 256e3,
		maxTokens: 4096
	},
	{
		id: "kimi-k2-5-260127",
		name: "Kimi K2.5",
		reasoning: false,
		input: ["text", "image"],
		contextWindow: 256e3,
		maxTokens: 4096
	},
	{
		id: "glm-4-7-251222",
		name: "GLM 4.7",
		reasoning: false,
		input: ["text", "image"],
		contextWindow: 2e5,
		maxTokens: 4096
	}
];
function buildBytePlusModelDefinition(entry) {
	return {
		id: entry.id,
		name: entry.name,
		reasoning: entry.reasoning,
		input: [...entry.input],
		cost: BYTEPLUS_DEFAULT_COST,
		contextWindow: entry.contextWindow,
		maxTokens: entry.maxTokens
	};
}
const BYTEPLUS_CODING_MODEL_CATALOG = [
	{
		id: "ark-code-latest",
		name: "Ark Coding Plan",
		reasoning: false,
		input: ["text"],
		contextWindow: 256e3,
		maxTokens: 4096
	},
	{
		id: "doubao-seed-code",
		name: "Doubao Seed Code",
		reasoning: false,
		input: ["text"],
		contextWindow: 256e3,
		maxTokens: 4096
	},
	{
		id: "glm-4.7",
		name: "GLM 4.7 Coding",
		reasoning: false,
		input: ["text"],
		contextWindow: 2e5,
		maxTokens: 4096
	},
	{
		id: "kimi-k2-thinking",
		name: "Kimi K2 Thinking",
		reasoning: false,
		input: ["text"],
		contextWindow: 256e3,
		maxTokens: 4096
	},
	{
		id: "kimi-k2.5",
		name: "Kimi K2.5 Coding",
		reasoning: false,
		input: ["text"],
		contextWindow: 256e3,
		maxTokens: 4096
	}
];

//#endregion
//#region src/agents/cloudflare-ai-gateway.ts
const CLOUDFLARE_AI_GATEWAY_PROVIDER_ID = "cloudflare-ai-gateway";
const CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_ID = "claude-sonnet-4-5";
const CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF = `${CLOUDFLARE_AI_GATEWAY_PROVIDER_ID}/${CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_ID}`;
const CLOUDFLARE_AI_GATEWAY_DEFAULT_CONTEXT_WINDOW = 2e5;
const CLOUDFLARE_AI_GATEWAY_DEFAULT_MAX_TOKENS = 64e3;
const CLOUDFLARE_AI_GATEWAY_DEFAULT_COST = {
	input: 3,
	output: 15,
	cacheRead: .3,
	cacheWrite: 3.75
};
function buildCloudflareAiGatewayModelDefinition(params) {
	return {
		id: params?.id?.trim() || CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_ID,
		name: params?.name ?? "Claude Sonnet 4.5",
		reasoning: params?.reasoning ?? true,
		input: params?.input ?? ["text", "image"],
		cost: CLOUDFLARE_AI_GATEWAY_DEFAULT_COST,
		contextWindow: CLOUDFLARE_AI_GATEWAY_DEFAULT_CONTEXT_WINDOW,
		maxTokens: CLOUDFLARE_AI_GATEWAY_DEFAULT_MAX_TOKENS
	};
}
function resolveCloudflareAiGatewayBaseUrl(params) {
	const accountId = params.accountId.trim();
	const gatewayId = params.gatewayId.trim();
	if (!accountId || !gatewayId) return "";
	return `https://gateway.ai.cloudflare.com/v1/${accountId}/${gatewayId}/anthropic`;
}

//#endregion
//#region src/agents/doubao-models.ts
const DOUBAO_BASE_URL = "https://ark.cn-beijing.volces.com/api/v3";
const DOUBAO_CODING_BASE_URL = "https://ark.cn-beijing.volces.com/api/coding/v3";
const DOUBAO_DEFAULT_MODEL_ID = "doubao-seed-1-8-251228";
const DOUBAO_DEFAULT_MODEL_REF = `volcengine/${DOUBAO_DEFAULT_MODEL_ID}`;
const DOUBAO_DEFAULT_COST = {
	input: 1e-4,
	output: 2e-4,
	cacheRead: 0,
	cacheWrite: 0
};
/**
* Complete catalog of Volcano Engine models.
*
* Volcano Engine provides access to models
* through the API. Authentication requires a Volcano Engine API Key.
*/
const DOUBAO_MODEL_CATALOG = [
	{
		id: "doubao-seed-code-preview-251028",
		name: "doubao-seed-code-preview-251028",
		reasoning: false,
		input: ["text", "image"],
		contextWindow: 256e3,
		maxTokens: 4096
	},
	{
		id: "doubao-seed-1-8-251228",
		name: "Doubao Seed 1.8",
		reasoning: false,
		input: ["text", "image"],
		contextWindow: 256e3,
		maxTokens: 4096
	},
	{
		id: "kimi-k2-5-260127",
		name: "Kimi K2.5",
		reasoning: false,
		input: ["text", "image"],
		contextWindow: 256e3,
		maxTokens: 4096
	},
	{
		id: "glm-4-7-251222",
		name: "GLM 4.7",
		reasoning: false,
		input: ["text", "image"],
		contextWindow: 2e5,
		maxTokens: 4096
	},
	{
		id: "deepseek-v3-2-251201",
		name: "DeepSeek V3.2",
		reasoning: false,
		input: ["text", "image"],
		contextWindow: 128e3,
		maxTokens: 4096
	}
];
function buildDoubaoModelDefinition(entry) {
	return {
		id: entry.id,
		name: entry.name,
		reasoning: entry.reasoning,
		input: [...entry.input],
		cost: DOUBAO_DEFAULT_COST,
		contextWindow: entry.contextWindow,
		maxTokens: entry.maxTokens
	};
}
const DOUBAO_CODING_MODEL_CATALOG = [
	{
		id: "ark-code-latest",
		name: "Ark Coding Plan",
		reasoning: false,
		input: ["text"],
		contextWindow: 256e3,
		maxTokens: 4096
	},
	{
		id: "doubao-seed-code",
		name: "Doubao Seed Code",
		reasoning: false,
		input: ["text"],
		contextWindow: 256e3,
		maxTokens: 4096
	},
	{
		id: "glm-4.7",
		name: "GLM 4.7 Coding",
		reasoning: false,
		input: ["text"],
		contextWindow: 2e5,
		maxTokens: 4096
	},
	{
		id: "kimi-k2-thinking",
		name: "Kimi K2 Thinking",
		reasoning: false,
		input: ["text"],
		contextWindow: 256e3,
		maxTokens: 4096
	},
	{
		id: "kimi-k2.5",
		name: "Kimi K2.5 Coding",
		reasoning: false,
		input: ["text"],
		contextWindow: 256e3,
		maxTokens: 4096
	},
	{
		id: "doubao-seed-code-preview-251028",
		name: "Doubao Seed Code Preview",
		reasoning: false,
		input: ["text"],
		contextWindow: 256e3,
		maxTokens: 4096
	}
];

//#endregion
//#region src/agents/huggingface-models.ts
/** Hugging Face Inference Providers (router) — OpenAI-compatible chat completions. */
const HUGGINGFACE_BASE_URL = "https://router.huggingface.co/v1";
/** Router policy suffixes: router picks backend by cost or speed; no specific provider selection. */
const HUGGINGFACE_POLICY_SUFFIXES = ["cheapest", "fastest"];
/**
* True when the model ref uses :cheapest or :fastest. When true, provider choice is locked
* (router decides); do not show an interactive "prefer specific backend" option.
*/
function isHuggingfacePolicyLocked(modelRef) {
	const ref = String(modelRef).trim();
	return HUGGINGFACE_POLICY_SUFFIXES.some((s) => ref.endsWith(`:${s}`) || ref === s);
}
/** Default cost when not in static catalog (HF pricing varies by provider). */
const HUGGINGFACE_DEFAULT_COST = {
	input: 0,
	output: 0,
	cacheRead: 0,
	cacheWrite: 0
};
/** Defaults for models discovered from GET /v1/models. */
const HUGGINGFACE_DEFAULT_CONTEXT_WINDOW = 131072;
const HUGGINGFACE_DEFAULT_MAX_TOKENS = 8192;
const HUGGINGFACE_MODEL_CATALOG = [
	{
		id: "deepseek-ai/DeepSeek-R1",
		name: "DeepSeek R1",
		reasoning: true,
		input: ["text"],
		contextWindow: 131072,
		maxTokens: 8192,
		cost: {
			input: 3,
			output: 7,
			cacheRead: 3,
			cacheWrite: 3
		}
	},
	{
		id: "deepseek-ai/DeepSeek-V3.1",
		name: "DeepSeek V3.1",
		reasoning: false,
		input: ["text"],
		contextWindow: 131072,
		maxTokens: 8192,
		cost: {
			input: .6,
			output: 1.25,
			cacheRead: .6,
			cacheWrite: .6
		}
	},
	{
		id: "meta-llama/Llama-3.3-70B-Instruct-Turbo",
		name: "Llama 3.3 70B Instruct Turbo",
		reasoning: false,
		input: ["text"],
		contextWindow: 131072,
		maxTokens: 8192,
		cost: {
			input: .88,
			output: .88,
			cacheRead: .88,
			cacheWrite: .88
		}
	},
	{
		id: "openai/gpt-oss-120b",
		name: "GPT-OSS 120B",
		reasoning: false,
		input: ["text"],
		contextWindow: 131072,
		maxTokens: 32768,
		cost: {
			input: 0,
			output: 0,
			cacheRead: 0,
			cacheWrite: 0
		}
	}
];
function buildHuggingfaceModelDefinition(model) {
	return {
		id: model.id,
		name: model.name,
		reasoning: model.reasoning,
		input: model.input,
		cost: model.cost,
		contextWindow: model.contextWindow,
		maxTokens: model.maxTokens
	};
}
/**
* Infer reasoning and display name from Hub-style model id (e.g. "deepseek-ai/DeepSeek-R1").
*/
function inferredMetaFromModelId(id) {
	const base = id.split("/").pop() ?? id;
	const reasoning = /r1|reasoning|thinking|reason/i.test(id) || /-\d+[tb]?-thinking/i.test(base);
	return {
		name: base.replace(/-/g, " ").replace(/\b(\w)/g, (c) => c.toUpperCase()),
		reasoning
	};
}
/** Prefer API-supplied display name, then owned_by/id, then inferred from id. */
function displayNameFromApiEntry(entry, inferredName) {
	const fromApi = typeof entry.name === "string" && entry.name.trim() || typeof entry.title === "string" && entry.title.trim() || typeof entry.display_name === "string" && entry.display_name.trim();
	if (fromApi) return fromApi;
	if (typeof entry.owned_by === "string" && entry.owned_by.trim()) {
		const base = entry.id.split("/").pop() ?? entry.id;
		return `${entry.owned_by.trim()}/${base}`;
	}
	return inferredName;
}
/**
* Discover chat-completion models from Hugging Face Inference Providers (GET /v1/models).
* Requires a valid HF token. Falls back to static catalog on failure or in test env.
*/
async function discoverHuggingfaceModels(apiKey) {
	if (process.env.VITEST === "true" || false) return HUGGINGFACE_MODEL_CATALOG.map(buildHuggingfaceModelDefinition);
	const trimmedKey = apiKey?.trim();
	if (!trimmedKey) return HUGGINGFACE_MODEL_CATALOG.map(buildHuggingfaceModelDefinition);
	try {
		const response = await fetch(`${HUGGINGFACE_BASE_URL}/models`, {
			signal: AbortSignal.timeout(1e4),
			headers: {
				Authorization: `Bearer ${trimmedKey}`,
				"Content-Type": "application/json"
			}
		});
		if (!response.ok) {
			console.warn(`[huggingface-models] GET /v1/models failed: HTTP ${response.status}, using static catalog`);
			return HUGGINGFACE_MODEL_CATALOG.map(buildHuggingfaceModelDefinition);
		}
		const data = (await response.json())?.data;
		if (!Array.isArray(data) || data.length === 0) {
			console.warn("[huggingface-models] No models in response, using static catalog");
			return HUGGINGFACE_MODEL_CATALOG.map(buildHuggingfaceModelDefinition);
		}
		const catalogById = new Map(HUGGINGFACE_MODEL_CATALOG.map((m) => [m.id, m]));
		const seen = /* @__PURE__ */ new Set();
		const models = [];
		for (const entry of data) {
			const id = typeof entry?.id === "string" ? entry.id.trim() : "";
			if (!id || seen.has(id)) continue;
			seen.add(id);
			const catalogEntry = catalogById.get(id);
			if (catalogEntry) models.push(buildHuggingfaceModelDefinition(catalogEntry));
			else {
				const inferred = inferredMetaFromModelId(id);
				const name = displayNameFromApiEntry(entry, inferred.name);
				const modalities = entry.architecture?.input_modalities;
				const input = Array.isArray(modalities) && modalities.includes("image") ? ["text", "image"] : ["text"];
				const contextLength = (Array.isArray(entry.providers) ? entry.providers : []).find((p) => typeof p?.context_length === "number" && p.context_length > 0)?.context_length ?? HUGGINGFACE_DEFAULT_CONTEXT_WINDOW;
				models.push({
					id,
					name,
					reasoning: inferred.reasoning,
					input,
					cost: HUGGINGFACE_DEFAULT_COST,
					contextWindow: contextLength,
					maxTokens: HUGGINGFACE_DEFAULT_MAX_TOKENS
				});
			}
		}
		return models.length > 0 ? models : HUGGINGFACE_MODEL_CATALOG.map(buildHuggingfaceModelDefinition);
	} catch (error) {
		console.warn(`[huggingface-models] Discovery failed: ${String(error)}, using static catalog`);
		return HUGGINGFACE_MODEL_CATALOG.map(buildHuggingfaceModelDefinition);
	}
}

//#endregion
//#region src/agents/ollama-stream.ts
const OLLAMA_NATIVE_BASE_URL = "http://127.0.0.1:11434";
const OLLAMA_MAX_RETRIES = 2;
const OLLAMA_RETRY_DELAY_MS = 1e3;
const OLLAMA_RETRYABLE_STATUS_CODES = new Set([
	500,
	502,
	503
]);
function extractTextContent(content) {
	if (typeof content === "string") return content;
	if (!Array.isArray(content)) return "";
	return content.filter((part) => part.type === "text").map((part) => part.text).join("");
}
function extractOllamaImages(content) {
	if (!Array.isArray(content)) return [];
	return content.filter((part) => part.type === "image").map((part) => part.data);
}
function extractToolCalls(content) {
	if (!Array.isArray(content)) return [];
	const parts = content;
	const result = [];
	for (const part of parts) if (part.type === "toolCall") result.push({ function: {
		name: part.name,
		arguments: part.arguments
	} });
	else if (part.type === "tool_use") result.push({ function: {
		name: part.name,
		arguments: part.input
	} });
	return result;
}
function convertToOllamaMessages(messages, system) {
	const result = [];
	if (system) result.push({
		role: "system",
		content: system
	});
	for (const msg of messages) {
		const { role } = msg;
		if (role === "user") {
			const text = extractTextContent(msg.content);
			const images = extractOllamaImages(msg.content);
			result.push({
				role: "user",
				content: text,
				...images.length > 0 ? { images } : {}
			});
		} else if (role === "assistant") {
			const text = extractTextContent(msg.content);
			const toolCalls = extractToolCalls(msg.content);
			result.push({
				role: "assistant",
				content: text,
				...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
			});
		} else if (role === "tool" || role === "toolResult") {
			const text = extractTextContent(msg.content);
			const toolName = typeof msg.toolName === "string" ? msg.toolName : void 0;
			result.push({
				role: "tool",
				content: text,
				...toolName ? { tool_name: toolName } : {}
			});
		}
	}
	return result;
}
function extractOllamaTools(tools) {
	if (!tools || !Array.isArray(tools)) return [];
	const result = [];
	for (const tool of tools) {
		if (typeof tool.name !== "string" || !tool.name) continue;
		result.push({
			type: "function",
			function: {
				name: tool.name,
				description: typeof tool.description === "string" ? tool.description : "",
				parameters: tool.parameters ?? {}
			}
		});
	}
	return result;
}
function buildAssistantMessage(response, modelInfo) {
	const content = [];
	const text = response.message.content || response.message.reasoning || response.message.thinking || "";
	if (text) content.push({
		type: "text",
		text
	});
	const toolCalls = response.message.tool_calls;
	if (toolCalls && toolCalls.length > 0) for (const tc of toolCalls) content.push({
		type: "toolCall",
		id: `ollama_call_${randomUUID()}`,
		name: tc.function.name,
		arguments: tc.function.arguments
	});
	const stopReason = toolCalls && toolCalls.length > 0 ? "toolUse" : "stop";
	const usage = {
		input: response.prompt_eval_count ?? 0,
		output: response.eval_count ?? 0,
		cacheRead: 0,
		cacheWrite: 0,
		totalTokens: (response.prompt_eval_count ?? 0) + (response.eval_count ?? 0),
		cost: {
			input: 0,
			output: 0,
			cacheRead: 0,
			cacheWrite: 0,
			total: 0
		}
	};
	return {
		role: "assistant",
		content,
		stopReason,
		api: modelInfo.api,
		provider: modelInfo.provider,
		model: modelInfo.id,
		usage,
		timestamp: Date.now()
	};
}
const INTER_CHUNK_TIMEOUT_MS = 3e5;
function readWithTimeout(reader, timeoutMs, signal) {
	return new Promise((resolve, reject) => {
		if (signal?.aborted) {
			reader.cancel("aborted").catch(() => {});
			reject(new DOMException("Ollama stream aborted by run timeout", "AbortError"));
			return;
		}
		const timer = setTimeout(() => {
			reader.cancel("inter-chunk timeout").catch(() => {});
			reject(/* @__PURE__ */ new Error(`Ollama stream stalled: no data received for ${timeoutMs / 1e3}s`));
		}, timeoutMs);
		const onAbort = () => {
			clearTimeout(timer);
			reader.cancel("aborted").catch(() => {});
			reject(new DOMException("Ollama stream aborted by run timeout", "AbortError"));
		};
		signal?.addEventListener("abort", onAbort, { once: true });
		reader.read().then((result) => {
			clearTimeout(timer);
			signal?.removeEventListener("abort", onAbort);
			resolve(result);
		}, (err) => {
			clearTimeout(timer);
			signal?.removeEventListener("abort", onAbort);
			reject(err);
		});
	});
}
async function* parseNdjsonStream(reader, signal) {
	const decoder = new TextDecoder();
	let buffer = "";
	while (true) {
		const { done, value } = await readWithTimeout(reader, INTER_CHUNK_TIMEOUT_MS, signal);
		if (done) break;
		buffer += decoder.decode(value, { stream: true });
		const lines = buffer.split("\n");
		buffer = lines.pop() ?? "";
		for (const line of lines) {
			const trimmed = line.trim();
			if (!trimmed) continue;
			try {
				yield JSON.parse(trimmed);
			} catch {
				console.warn("[ollama-stream] Skipping malformed NDJSON line:", trimmed.slice(0, 120));
			}
		}
	}
	if (buffer.trim()) try {
		yield JSON.parse(buffer.trim());
	} catch {
		console.warn("[ollama-stream] Skipping malformed trailing data:", buffer.trim().slice(0, 120));
	}
}
function resolveOllamaChatUrl(baseUrl) {
	return `${baseUrl.trim().replace(/\/+$/, "").replace(/\/v1$/i, "") || OLLAMA_NATIVE_BASE_URL}/api/chat`;
}
function createOllamaStreamFn(baseUrl) {
	const chatUrl = resolveOllamaChatUrl(baseUrl);
	return (model, context, options) => {
		const stream = createAssistantMessageEventStream();
		const run = async () => {
			try {
				const ollamaMessages = convertToOllamaMessages(context.messages ?? [], context.systemPrompt);
				const ollamaTools = extractOllamaTools(context.tools);
				const ollamaOptions = { num_ctx: model.contextWindow ?? 65536 };
				if (typeof options?.temperature === "number") ollamaOptions.temperature = options.temperature;
				if (typeof options?.maxTokens === "number") ollamaOptions.num_predict = options.maxTokens;
				const opts = options;
				if (typeof opts?.top_p === "number") ollamaOptions.top_p = opts.top_p;
				if (typeof opts?.top_k === "number") ollamaOptions.top_k = opts.top_k;
				if (typeof opts?.repeat_penalty === "number") ollamaOptions.repeat_penalty = opts.repeat_penalty;
				const chatTemplateKwargs = opts?.chat_template_kwargs && typeof opts.chat_template_kwargs === "object" ? opts.chat_template_kwargs : void 0;
				const body = {
					model: model.id,
					messages: ollamaMessages,
					stream: true,
					...ollamaTools.length > 0 ? { tools: ollamaTools } : {},
					options: ollamaOptions,
					...chatTemplateKwargs ? { chat_template_kwargs: chatTemplateKwargs } : {}
				};
				const headers = {
					"Content-Type": "application/json",
					...options?.headers
				};
				if (options?.apiKey) headers.Authorization = `Bearer ${options.apiKey}`;
				let response;
				let lastError = "";
				for (let attempt = 0; attempt <= OLLAMA_MAX_RETRIES; attempt++) {
					if (attempt > 0) {
						console.warn(`[ollama-stream] Retrying after HTTP ${response?.status} (attempt ${attempt + 1}/${OLLAMA_MAX_RETRIES + 1}): ${lastError.slice(0, 200)}`);
						await new Promise((r) => setTimeout(r, OLLAMA_RETRY_DELAY_MS * attempt));
						if (options?.signal?.aborted) throw new DOMException("Ollama stream aborted during retry", "AbortError");
					}
					response = await fetch(chatUrl, {
						method: "POST",
						headers,
						body: JSON.stringify(body),
						signal: options?.signal
					});
					if (response.ok) break;
					lastError = await response.text().catch(() => "unknown error");
					if (!OLLAMA_RETRYABLE_STATUS_CODES.has(response.status) || attempt === OLLAMA_MAX_RETRIES) throw new Error(`Ollama API error ${response.status}: ${lastError}`);
				}
				if (!response.body) throw new Error("Ollama API returned empty response body");
				const reader = response.body.getReader();
				let accumulatedContent = "";
				let accumulatedThinking = "";
				const accumulatedToolCalls = [];
				let finalResponse;
				for await (const chunk of parseNdjsonStream(reader, options?.signal)) {
					if (chunk.message?.content) accumulatedContent += chunk.message.content;
					else if (chunk.message?.reasoning) accumulatedContent += chunk.message.reasoning;
					else if (chunk.message?.thinking) accumulatedThinking += chunk.message.thinking;
					if (chunk.message?.tool_calls) accumulatedToolCalls.push(...chunk.message.tool_calls);
					if (chunk.done) {
						finalResponse = chunk;
						break;
					}
				}
				if (!finalResponse) {
					if (options?.signal?.aborted) throw new DOMException("Ollama stream aborted: run timeout exceeded. The model's context was too large for the configured timeout. Increase the per-model timeoutSeconds or reduce context size.", "AbortError");
					throw new Error("Ollama API stream ended without a final response");
				}
				const hasTools = ollamaTools.length > 0;
				if (!accumulatedContent && accumulatedToolCalls.length === 0 && accumulatedThinking.length > 0 && hasTools) {
					console.warn(`[ollama-stream] thinking-only response detected (${accumulatedThinking.length} thinking chars, 0 content, 0 tool calls). Allowing verification pass to recover.`);
					finalResponse.message.content = "";
				}
				finalResponse.message.content = accumulatedContent || (accumulatedToolCalls.length === 0 ? accumulatedThinking : "");
				if (accumulatedToolCalls.length > 0) finalResponse.message.tool_calls = accumulatedToolCalls;
				const assistantMessage = buildAssistantMessage(finalResponse, {
					api: model.api,
					provider: model.provider,
					id: model.id
				});
				const reason = assistantMessage.stopReason === "toolUse" ? "toolUse" : "stop";
				stream.push({
					type: "done",
					reason,
					message: assistantMessage
				});
			} catch (err) {
				const errorMessage = err instanceof Error ? err.message : String(err);
				stream.push({
					type: "error",
					reason: "error",
					error: {
						role: "assistant",
						content: [],
						stopReason: "error",
						errorMessage,
						api: model.api,
						provider: model.provider,
						model: model.id,
						usage: {
							input: 0,
							output: 0,
							cacheRead: 0,
							cacheWrite: 0,
							totalTokens: 0,
							cost: {
								input: 0,
								output: 0,
								cacheRead: 0,
								cacheWrite: 0,
								total: 0
							}
						},
						timestamp: Date.now()
					}
				});
			} finally {
				stream.end();
			}
		};
		queueMicrotask(() => void run());
		return stream;
	};
}

//#endregion
//#region src/agents/synthetic-models.ts
const SYNTHETIC_BASE_URL = "https://api.synthetic.new/anthropic";
const SYNTHETIC_DEFAULT_MODEL_ID = "hf:MiniMaxAI/MiniMax-M2.1";
const SYNTHETIC_DEFAULT_MODEL_REF = `synthetic/${SYNTHETIC_DEFAULT_MODEL_ID}`;
const SYNTHETIC_DEFAULT_COST = {
	input: 0,
	output: 0,
	cacheRead: 0,
	cacheWrite: 0
};
const SYNTHETIC_MODEL_CATALOG = [
	{
		id: SYNTHETIC_DEFAULT_MODEL_ID,
		name: "MiniMax M2.1",
		reasoning: false,
		input: ["text"],
		contextWindow: 192e3,
		maxTokens: 65536
	},
	{
		id: "hf:moonshotai/Kimi-K2-Thinking",
		name: "Kimi K2 Thinking",
		reasoning: true,
		input: ["text"],
		contextWindow: 256e3,
		maxTokens: 8192
	},
	{
		id: "hf:zai-org/GLM-4.7",
		name: "GLM-4.7",
		reasoning: false,
		input: ["text"],
		contextWindow: 198e3,
		maxTokens: 128e3
	},
	{
		id: "hf:deepseek-ai/DeepSeek-R1-0528",
		name: "DeepSeek R1 0528",
		reasoning: false,
		input: ["text"],
		contextWindow: 128e3,
		maxTokens: 8192
	},
	{
		id: "hf:deepseek-ai/DeepSeek-V3-0324",
		name: "DeepSeek V3 0324",
		reasoning: false,
		input: ["text"],
		contextWindow: 128e3,
		maxTokens: 8192
	},
	{
		id: "hf:deepseek-ai/DeepSeek-V3.1",
		name: "DeepSeek V3.1",
		reasoning: false,
		input: ["text"],
		contextWindow: 128e3,
		maxTokens: 8192
	},
	{
		id: "hf:deepseek-ai/DeepSeek-V3.1-Terminus",
		name: "DeepSeek V3.1 Terminus",
		reasoning: false,
		input: ["text"],
		contextWindow: 128e3,
		maxTokens: 8192
	},
	{
		id: "hf:deepseek-ai/DeepSeek-V3.2",
		name: "DeepSeek V3.2",
		reasoning: false,
		input: ["text"],
		contextWindow: 159e3,
		maxTokens: 8192
	},
	{
		id: "hf:meta-llama/Llama-3.3-70B-Instruct",
		name: "Llama 3.3 70B Instruct",
		reasoning: false,
		input: ["text"],
		contextWindow: 128e3,
		maxTokens: 8192
	},
	{
		id: "hf:meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8",
		name: "Llama 4 Maverick 17B 128E Instruct FP8",
		reasoning: false,
		input: ["text"],
		contextWindow: 524e3,
		maxTokens: 8192
	},
	{
		id: "hf:moonshotai/Kimi-K2-Instruct-0905",
		name: "Kimi K2 Instruct 0905",
		reasoning: false,
		input: ["text"],
		contextWindow: 256e3,
		maxTokens: 8192
	},
	{
		id: "hf:moonshotai/Kimi-K2.5",
		name: "Kimi K2.5",
		reasoning: true,
		input: ["text"],
		contextWindow: 256e3,
		maxTokens: 8192
	},
	{
		id: "hf:openai/gpt-oss-120b",
		name: "GPT OSS 120B",
		reasoning: false,
		input: ["text"],
		contextWindow: 128e3,
		maxTokens: 32768
	},
	{
		id: "hf:Qwen/Qwen3-235B-A22B-Instruct-2507",
		name: "Qwen3 235B A22B Instruct 2507",
		reasoning: false,
		input: ["text"],
		contextWindow: 256e3,
		maxTokens: 8192
	},
	{
		id: "hf:Qwen/Qwen3-Coder-480B-A35B-Instruct",
		name: "Qwen3 Coder 480B A35B Instruct",
		reasoning: false,
		input: ["text"],
		contextWindow: 256e3,
		maxTokens: 8192
	},
	{
		id: "hf:Qwen/Qwen3-VL-235B-A22B-Instruct",
		name: "Qwen3 VL 235B A22B Instruct",
		reasoning: false,
		input: ["text", "image"],
		contextWindow: 25e4,
		maxTokens: 8192
	},
	{
		id: "hf:zai-org/GLM-4.5",
		name: "GLM-4.5",
		reasoning: false,
		input: ["text"],
		contextWindow: 128e3,
		maxTokens: 128e3
	},
	{
		id: "hf:zai-org/GLM-4.6",
		name: "GLM-4.6",
		reasoning: false,
		input: ["text"],
		contextWindow: 198e3,
		maxTokens: 128e3
	},
	{
		id: "hf:zai-org/GLM-5",
		name: "GLM-5",
		reasoning: true,
		input: ["text", "image"],
		contextWindow: 256e3,
		maxTokens: 128e3
	},
	{
		id: "hf:deepseek-ai/DeepSeek-V3",
		name: "DeepSeek V3",
		reasoning: false,
		input: ["text"],
		contextWindow: 128e3,
		maxTokens: 8192
	},
	{
		id: "hf:Qwen/Qwen3-235B-A22B-Thinking-2507",
		name: "Qwen3 235B A22B Thinking 2507",
		reasoning: true,
		input: ["text"],
		contextWindow: 256e3,
		maxTokens: 8192
	}
];
function buildSyntheticModelDefinition(entry) {
	return {
		id: entry.id,
		name: entry.name,
		reasoning: entry.reasoning,
		input: [...entry.input],
		cost: SYNTHETIC_DEFAULT_COST,
		contextWindow: entry.contextWindow,
		maxTokens: entry.maxTokens
	};
}

//#endregion
//#region src/agents/together-models.ts
const TOGETHER_BASE_URL = "https://api.together.xyz/v1";
const TOGETHER_MODEL_CATALOG = [
	{
		id: "zai-org/GLM-4.7",
		name: "GLM 4.7 Fp8",
		reasoning: false,
		input: ["text"],
		contextWindow: 202752,
		maxTokens: 8192,
		cost: {
			input: .45,
			output: 2,
			cacheRead: .45,
			cacheWrite: 2
		}
	},
	{
		id: "moonshotai/Kimi-K2.5",
		name: "Kimi K2.5",
		reasoning: true,
		input: ["text", "image"],
		cost: {
			input: .5,
			output: 2.8,
			cacheRead: .5,
			cacheWrite: 2.8
		},
		contextWindow: 262144,
		maxTokens: 32768
	},
	{
		id: "meta-llama/Llama-3.3-70B-Instruct-Turbo",
		name: "Llama 3.3 70B Instruct Turbo",
		reasoning: false,
		input: ["text"],
		contextWindow: 131072,
		maxTokens: 8192,
		cost: {
			input: .88,
			output: .88,
			cacheRead: .88,
			cacheWrite: .88
		}
	},
	{
		id: "meta-llama/Llama-4-Scout-17B-16E-Instruct",
		name: "Llama 4 Scout 17B 16E Instruct",
		reasoning: false,
		input: ["text", "image"],
		contextWindow: 1e7,
		maxTokens: 32768,
		cost: {
			input: .18,
			output: .59,
			cacheRead: .18,
			cacheWrite: .18
		}
	},
	{
		id: "meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8",
		name: "Llama 4 Maverick 17B 128E Instruct FP8",
		reasoning: false,
		input: ["text", "image"],
		contextWindow: 2e7,
		maxTokens: 32768,
		cost: {
			input: .27,
			output: .85,
			cacheRead: .27,
			cacheWrite: .27
		}
	},
	{
		id: "deepseek-ai/DeepSeek-V3.1",
		name: "DeepSeek V3.1",
		reasoning: false,
		input: ["text"],
		contextWindow: 131072,
		maxTokens: 8192,
		cost: {
			input: .6,
			output: 1.25,
			cacheRead: .6,
			cacheWrite: .6
		}
	},
	{
		id: "deepseek-ai/DeepSeek-R1",
		name: "DeepSeek R1",
		reasoning: true,
		input: ["text"],
		contextWindow: 131072,
		maxTokens: 8192,
		cost: {
			input: 3,
			output: 7,
			cacheRead: 3,
			cacheWrite: 3
		}
	},
	{
		id: "moonshotai/Kimi-K2-Instruct-0905",
		name: "Kimi K2-Instruct 0905",
		reasoning: false,
		input: ["text"],
		contextWindow: 262144,
		maxTokens: 8192,
		cost: {
			input: 1,
			output: 3,
			cacheRead: 1,
			cacheWrite: 3
		}
	}
];
function buildTogetherModelDefinition(model) {
	return {
		id: model.id,
		name: model.name,
		api: "openai-completions",
		reasoning: model.reasoning,
		input: model.input,
		cost: model.cost,
		contextWindow: model.contextWindow,
		maxTokens: model.maxTokens
	};
}

//#endregion
//#region src/agents/venice-models.ts
const VENICE_BASE_URL = "https://api.venice.ai/api/v1";
const VENICE_DEFAULT_MODEL_ID = "llama-3.3-70b";
const VENICE_DEFAULT_MODEL_REF = `venice/${VENICE_DEFAULT_MODEL_ID}`;
const VENICE_DEFAULT_COST = {
	input: 0,
	output: 0,
	cacheRead: 0,
	cacheWrite: 0
};
/**
* Complete catalog of Venice AI models.
*
* Venice provides two privacy modes:
* - "private": Fully private inference, no logging, ephemeral
* - "anonymized": Proxied through Venice with metadata stripped (for proprietary models)
*
* Note: The `privacy` field is included for documentation purposes but is not
* propagated to ModelDefinitionConfig as it's not part of the core model schema.
* Privacy mode is determined by the model itself, not configurable at runtime.
*
* This catalog serves as a fallback when the Venice API is unreachable.
*/
const VENICE_MODEL_CATALOG = [
	{
		id: "llama-3.3-70b",
		name: "Llama 3.3 70B",
		reasoning: false,
		input: ["text"],
		contextWindow: 131072,
		maxTokens: 8192,
		privacy: "private"
	},
	{
		id: "llama-3.2-3b",
		name: "Llama 3.2 3B",
		reasoning: false,
		input: ["text"],
		contextWindow: 131072,
		maxTokens: 8192,
		privacy: "private"
	},
	{
		id: "hermes-3-llama-3.1-405b",
		name: "Hermes 3 Llama 3.1 405B",
		reasoning: false,
		input: ["text"],
		contextWindow: 131072,
		maxTokens: 8192,
		privacy: "private"
	},
	{
		id: "qwen3-235b-a22b-thinking-2507",
		name: "Qwen3 235B Thinking",
		reasoning: true,
		input: ["text"],
		contextWindow: 131072,
		maxTokens: 8192,
		privacy: "private"
	},
	{
		id: "qwen3-235b-a22b-instruct-2507",
		name: "Qwen3 235B Instruct",
		reasoning: false,
		input: ["text"],
		contextWindow: 131072,
		maxTokens: 8192,
		privacy: "private"
	},
	{
		id: "qwen3-coder-480b-a35b-instruct",
		name: "Qwen3 Coder 480B",
		reasoning: false,
		input: ["text"],
		contextWindow: 262144,
		maxTokens: 8192,
		privacy: "private"
	},
	{
		id: "qwen3-next-80b",
		name: "Qwen3 Next 80B",
		reasoning: false,
		input: ["text"],
		contextWindow: 262144,
		maxTokens: 8192,
		privacy: "private"
	},
	{
		id: "qwen3-vl-235b-a22b",
		name: "Qwen3 VL 235B (Vision)",
		reasoning: false,
		input: ["text", "image"],
		contextWindow: 262144,
		maxTokens: 8192,
		privacy: "private"
	},
	{
		id: "qwen3-4b",
		name: "Venice Small (Qwen3 4B)",
		reasoning: true,
		input: ["text"],
		contextWindow: 32768,
		maxTokens: 8192,
		privacy: "private"
	},
	{
		id: "deepseek-v3.2",
		name: "DeepSeek V3.2",
		reasoning: true,
		input: ["text"],
		contextWindow: 163840,
		maxTokens: 8192,
		privacy: "private"
	},
	{
		id: "venice-uncensored",
		name: "Venice Uncensored (Dolphin-Mistral)",
		reasoning: false,
		input: ["text"],
		contextWindow: 32768,
		maxTokens: 8192,
		privacy: "private"
	},
	{
		id: "mistral-31-24b",
		name: "Venice Medium (Mistral)",
		reasoning: false,
		input: ["text", "image"],
		contextWindow: 131072,
		maxTokens: 8192,
		privacy: "private"
	},
	{
		id: "google-gemma-3-27b-it",
		name: "Google Gemma 3 27B Instruct",
		reasoning: false,
		input: ["text", "image"],
		contextWindow: 202752,
		maxTokens: 8192,
		privacy: "private"
	},
	{
		id: "openai-gpt-oss-120b",
		name: "OpenAI GPT OSS 120B",
		reasoning: false,
		input: ["text"],
		contextWindow: 131072,
		maxTokens: 8192,
		privacy: "private"
	},
	{
		id: "zai-org-glm-4.7",
		name: "GLM 4.7",
		reasoning: true,
		input: ["text"],
		contextWindow: 202752,
		maxTokens: 8192,
		privacy: "private"
	},
	{
		id: "claude-opus-45",
		name: "Claude Opus 4.5 (via Venice)",
		reasoning: true,
		input: ["text", "image"],
		contextWindow: 202752,
		maxTokens: 8192,
		privacy: "anonymized"
	},
	{
		id: "claude-sonnet-45",
		name: "Claude Sonnet 4.5 (via Venice)",
		reasoning: true,
		input: ["text", "image"],
		contextWindow: 202752,
		maxTokens: 8192,
		privacy: "anonymized"
	},
	{
		id: "openai-gpt-52",
		name: "GPT-5.2 (via Venice)",
		reasoning: true,
		input: ["text"],
		contextWindow: 262144,
		maxTokens: 8192,
		privacy: "anonymized"
	},
	{
		id: "openai-gpt-52-codex",
		name: "GPT-5.2 Codex (via Venice)",
		reasoning: true,
		input: ["text", "image"],
		contextWindow: 262144,
		maxTokens: 8192,
		privacy: "anonymized"
	},
	{
		id: "gemini-3-pro-preview",
		name: "Gemini 3 Pro (via Venice)",
		reasoning: true,
		input: ["text", "image"],
		contextWindow: 202752,
		maxTokens: 8192,
		privacy: "anonymized"
	},
	{
		id: "gemini-3-flash-preview",
		name: "Gemini 3 Flash (via Venice)",
		reasoning: true,
		input: ["text", "image"],
		contextWindow: 262144,
		maxTokens: 8192,
		privacy: "anonymized"
	},
	{
		id: "grok-41-fast",
		name: "Grok 4.1 Fast (via Venice)",
		reasoning: true,
		input: ["text", "image"],
		contextWindow: 262144,
		maxTokens: 8192,
		privacy: "anonymized"
	},
	{
		id: "grok-code-fast-1",
		name: "Grok Code Fast 1 (via Venice)",
		reasoning: true,
		input: ["text"],
		contextWindow: 262144,
		maxTokens: 8192,
		privacy: "anonymized"
	},
	{
		id: "kimi-k2-thinking",
		name: "Kimi K2 Thinking (via Venice)",
		reasoning: true,
		input: ["text"],
		contextWindow: 262144,
		maxTokens: 8192,
		privacy: "anonymized"
	},
	{
		id: "minimax-m21",
		name: "MiniMax M2.1 (via Venice)",
		reasoning: true,
		input: ["text"],
		contextWindow: 202752,
		maxTokens: 8192,
		privacy: "anonymized"
	}
];
/**
* Build a ModelDefinitionConfig from a Venice catalog entry.
*
* Note: The `privacy` field from the catalog is not included in the output
* as ModelDefinitionConfig doesn't support custom metadata fields. Privacy
* mode is inherent to each model and documented in the catalog/docs.
*/
function buildVeniceModelDefinition(entry) {
	return {
		id: entry.id,
		name: entry.name,
		reasoning: entry.reasoning,
		input: [...entry.input],
		cost: VENICE_DEFAULT_COST,
		contextWindow: entry.contextWindow,
		maxTokens: entry.maxTokens,
		compat: { supportsUsageInStreaming: false }
	};
}
/**
* Discover models from Venice API with fallback to static catalog.
* The /models endpoint is public and doesn't require authentication.
*/
async function discoverVeniceModels() {
	if (process.env.VITEST) return VENICE_MODEL_CATALOG.map(buildVeniceModelDefinition);
	try {
		const response = await fetch(`${VENICE_BASE_URL}/models`, { signal: AbortSignal.timeout(5e3) });
		if (!response.ok) {
			console.warn(`[venice-models] Failed to discover models: HTTP ${response.status}, using static catalog`);
			return VENICE_MODEL_CATALOG.map(buildVeniceModelDefinition);
		}
		const data = await response.json();
		if (!Array.isArray(data.data) || data.data.length === 0) {
			console.warn("[venice-models] No models found from API, using static catalog");
			return VENICE_MODEL_CATALOG.map(buildVeniceModelDefinition);
		}
		const catalogById = new Map(VENICE_MODEL_CATALOG.map((m) => [m.id, m]));
		const models = [];
		for (const apiModel of data.data) {
			const catalogEntry = catalogById.get(apiModel.id);
			if (catalogEntry) models.push(buildVeniceModelDefinition(catalogEntry));
			else {
				const isReasoning = apiModel.model_spec.capabilities.supportsReasoning || apiModel.id.toLowerCase().includes("thinking") || apiModel.id.toLowerCase().includes("reason") || apiModel.id.toLowerCase().includes("r1");
				const hasVision = apiModel.model_spec.capabilities.supportsVision;
				models.push({
					id: apiModel.id,
					name: apiModel.model_spec.name || apiModel.id,
					reasoning: isReasoning,
					input: hasVision ? ["text", "image"] : ["text"],
					cost: VENICE_DEFAULT_COST,
					contextWindow: apiModel.model_spec.availableContextTokens || 128e3,
					maxTokens: 8192,
					compat: { supportsUsageInStreaming: false }
				});
			}
		}
		return models.length > 0 ? models : VENICE_MODEL_CATALOG.map(buildVeniceModelDefinition);
	} catch (error) {
		console.warn(`[venice-models] Discovery failed: ${String(error)}, using static catalog`);
		return VENICE_MODEL_CATALOG.map(buildVeniceModelDefinition);
	}
}

//#endregion
//#region src/agents/models-config.providers.ts
const MINIMAX_PORTAL_BASE_URL = "https://api.minimax.io/anthropic";
const MINIMAX_DEFAULT_MODEL_ID = "MiniMax-M2.1";
const MINIMAX_DEFAULT_VISION_MODEL_ID = "MiniMax-VL-01";
const MINIMAX_DEFAULT_CONTEXT_WINDOW = 2e5;
const MINIMAX_DEFAULT_MAX_TOKENS = 8192;
const MINIMAX_OAUTH_PLACEHOLDER = "minimax-oauth";
const MINIMAX_API_COST = {
	input: 15,
	output: 60,
	cacheRead: 2,
	cacheWrite: 10
};
function buildMinimaxModel(params) {
	return {
		id: params.id,
		name: params.name,
		reasoning: params.reasoning,
		input: params.input,
		cost: MINIMAX_API_COST,
		contextWindow: MINIMAX_DEFAULT_CONTEXT_WINDOW,
		maxTokens: MINIMAX_DEFAULT_MAX_TOKENS
	};
}
function buildMinimaxTextModel(params) {
	return buildMinimaxModel({
		...params,
		input: ["text"]
	});
}
const XIAOMI_BASE_URL = "https://api.xiaomimimo.com/anthropic";
const XIAOMI_DEFAULT_MODEL_ID = "mimo-v2-flash";
const XIAOMI_DEFAULT_CONTEXT_WINDOW = 262144;
const XIAOMI_DEFAULT_MAX_TOKENS = 8192;
const XIAOMI_DEFAULT_COST = {
	input: 0,
	output: 0,
	cacheRead: 0,
	cacheWrite: 0
};
const MOONSHOT_BASE_URL = "https://api.moonshot.ai/v1";
const MOONSHOT_DEFAULT_MODEL_ID = "kimi-k2.5";
const MOONSHOT_DEFAULT_CONTEXT_WINDOW = 256e3;
const MOONSHOT_DEFAULT_MAX_TOKENS = 8192;
const MOONSHOT_DEFAULT_COST = {
	input: 0,
	output: 0,
	cacheRead: 0,
	cacheWrite: 0
};
const KIMI_CODING_BASE_URL = "https://api.kimi.com/coding/";
const KIMI_CODING_DEFAULT_MODEL_ID = "k2p5";
const KIMI_CODING_DEFAULT_CONTEXT_WINDOW = 262144;
const KIMI_CODING_DEFAULT_MAX_TOKENS = 32768;
const KIMI_CODING_DEFAULT_COST = {
	input: 0,
	output: 0,
	cacheRead: 0,
	cacheWrite: 0
};
const QWEN_PORTAL_BASE_URL = "https://portal.qwen.ai/v1";
const QWEN_PORTAL_OAUTH_PLACEHOLDER = "qwen-oauth";
const QWEN_PORTAL_DEFAULT_CONTEXT_WINDOW = 128e3;
const QWEN_PORTAL_DEFAULT_MAX_TOKENS = 8192;
const QWEN_PORTAL_DEFAULT_COST = {
	input: 0,
	output: 0,
	cacheRead: 0,
	cacheWrite: 0
};
const OLLAMA_API_BASE_URL = OLLAMA_NATIVE_BASE_URL;
const OLLAMA_DEFAULT_CONTEXT_WINDOW = 128e3;
const OLLAMA_DEFAULT_MAX_TOKENS = 8192;
const OLLAMA_DISCOVERY_TIMEOUT_MS = 1500;
const OLLAMA_DEFAULT_COST = {
	input: 0,
	output: 0,
	cacheRead: 0,
	cacheWrite: 0
};
const VLLM_BASE_URL = "http://127.0.0.1:8000/v1";
const VLLM_DEFAULT_CONTEXT_WINDOW = 128e3;
const VLLM_DEFAULT_MAX_TOKENS = 8192;
const VLLM_DEFAULT_COST = {
	input: 0,
	output: 0,
	cacheRead: 0,
	cacheWrite: 0
};
const QIANFAN_BASE_URL = "https://qianfan.baidubce.com/v2";
const QIANFAN_DEFAULT_MODEL_ID = "deepseek-v3.2";
const QIANFAN_DEFAULT_CONTEXT_WINDOW = 98304;
const QIANFAN_DEFAULT_MAX_TOKENS = 32768;
const QIANFAN_DEFAULT_COST = {
	input: 0,
	output: 0,
	cacheRead: 0,
	cacheWrite: 0
};
const NVIDIA_BASE_URL = "https://integrate.api.nvidia.com/v1";
const NVIDIA_DEFAULT_MODEL_ID = "nvidia/llama-3.1-nemotron-70b-instruct";
const NVIDIA_DEFAULT_CONTEXT_WINDOW = 131072;
const NVIDIA_DEFAULT_MAX_TOKENS = 4096;
const NVIDIA_DEFAULT_COST = {
	input: 0,
	output: 0,
	cacheRead: 0,
	cacheWrite: 0
};
/**
* Derive the Ollama native API base URL from a configured base URL.
*
* Users typically configure `baseUrl` with a `/v1` suffix (e.g.
* `http://192.168.20.14:11434/v1`) for the OpenAI-compatible endpoint.
* The native Ollama API lives at the root (e.g. `/api/tags`), so we
* strip the `/v1` suffix when present.
*/
function resolveOllamaApiBase(configuredBaseUrl) {
	if (!configuredBaseUrl) return OLLAMA_API_BASE_URL;
	return configuredBaseUrl.replace(/\/+$/, "").replace(/\/v1$/i, "");
}
async function discoverOllamaModels(baseUrl) {
	if (process.env.VITEST || false) return [];
	const apiBase = resolveOllamaApiBase(baseUrl);
	try {
		const response = await fetch(`${apiBase}/api/tags`, { signal: AbortSignal.timeout(OLLAMA_DISCOVERY_TIMEOUT_MS) });
		if (!response.ok) {
			console.warn(`Failed to discover Ollama models: ${response.status}`);
			return [];
		}
		const data = await response.json();
		if (!data.models || data.models.length === 0) {
			console.warn("No Ollama models found on local instance");
			return [];
		}
		return data.models.map((model) => {
			const modelId = model.name;
			return {
				id: modelId,
				name: modelId,
				reasoning: modelId.toLowerCase().includes("r1") || modelId.toLowerCase().includes("reasoning"),
				input: ["text"],
				cost: OLLAMA_DEFAULT_COST,
				contextWindow: OLLAMA_DEFAULT_CONTEXT_WINDOW,
				maxTokens: OLLAMA_DEFAULT_MAX_TOKENS
			};
		});
	} catch (error) {
		if (error instanceof Error && error.name === "TimeoutError") console.warn(`Ollama discovery timed out at ${apiBase} after ${OLLAMA_DISCOVERY_TIMEOUT_MS}ms. Provider unreachable — remove from config.json or fix endpoint to avoid per-turn latency.`);
		else console.warn(`Failed to discover Ollama models: ${String(error)}`);
		return [];
	}
}
async function discoverVllmModels(baseUrl, apiKey) {
	if (process.env.VITEST || false) return [];
	const url = `${baseUrl.trim().replace(/\/+$/, "")}/models`;
	try {
		const trimmedApiKey = apiKey?.trim();
		const response = await fetch(url, {
			headers: trimmedApiKey ? { Authorization: `Bearer ${trimmedApiKey}` } : void 0,
			signal: AbortSignal.timeout(5e3)
		});
		if (!response.ok) {
			console.warn(`Failed to discover vLLM models: ${response.status}`);
			return [];
		}
		const models = (await response.json()).data ?? [];
		if (models.length === 0) {
			console.warn("No vLLM models found on local instance");
			return [];
		}
		return models.map((m) => ({ id: typeof m.id === "string" ? m.id.trim() : "" })).filter((m) => Boolean(m.id)).map((m) => {
			const modelId = m.id;
			const lower = modelId.toLowerCase();
			return {
				id: modelId,
				name: modelId,
				reasoning: lower.includes("r1") || lower.includes("reasoning") || lower.includes("think"),
				input: ["text"],
				cost: VLLM_DEFAULT_COST,
				contextWindow: VLLM_DEFAULT_CONTEXT_WINDOW,
				maxTokens: VLLM_DEFAULT_MAX_TOKENS
			};
		});
	} catch (error) {
		console.warn(`Failed to discover vLLM models: ${String(error)}`);
		return [];
	}
}
function normalizeApiKeyConfig(value) {
	const trimmed = value.trim();
	return /^\$\{([A-Z0-9_]+)\}$/.exec(trimmed)?.[1] ?? trimmed;
}
function resolveEnvApiKeyVarName(provider) {
	const resolved = resolveEnvApiKey(provider);
	if (!resolved) return;
	const match = /^(?:env: |shell env: )([A-Z0-9_]+)$/.exec(resolved.source);
	return match ? match[1] : void 0;
}
function resolveAwsSdkApiKeyVarName() {
	return resolveAwsSdkEnvVarName() ?? "AWS_PROFILE";
}
function resolveApiKeyFromProfiles(params) {
	const ids = listProfilesForProvider(params.store, params.provider);
	for (const id of ids) {
		const cred = params.store.profiles[id];
		if (!cred) continue;
		if (cred.type === "api_key") return cred.key;
		if (cred.type === "token") return cred.token;
	}
}
function normalizeGoogleModelId(id) {
	if (id === "gemini-3-pro") return "gemini-3-pro-preview";
	if (id === "gemini-3-flash") return "gemini-3-flash-preview";
	return id;
}
function normalizeGoogleProvider(provider) {
	let mutated = false;
	const models = provider.models.map((model) => {
		const nextId = normalizeGoogleModelId(model.id);
		if (nextId === model.id) return model;
		mutated = true;
		return {
			...model,
			id: nextId
		};
	});
	return mutated ? {
		...provider,
		models
	} : provider;
}
/**
* Default-fill a model definition so downstream consumers (pi-ai's
* `ModelRegistry` and streaming providers) never crash on missing
* `cost` or `input` fields. Zod marks both as optional when parsing
* user `symi.json`, but `pi-ai/dist/models.js` reads `model.cost.input`
* unconditionally — a hand-rolled provider entry that omits either
* field throws a TypeError deep in the stream path with no body, which
* presents to the user as a fast isError=true with no useful log line.
*
* Defaults applied:
* - `input` → `["text"]` (safest; image support must be explicit)
* - `cost`  → all zeros (self-hosted / free-tier assumption)
*
* Explicit user values are preserved. Only missing fields are filled.
* Returns the same object reference if no change was needed so the
* caller's dirty-check stays accurate.
*/
function defaultFillModelDefinition(model) {
	const needsInput = !Array.isArray(model.input) || model.input.length === 0;
	const needsCost = !model.cost || typeof model.cost?.input !== "number" || typeof model.cost?.output !== "number" || typeof model.cost?.cacheRead !== "number" || typeof model.cost?.cacheWrite !== "number";
	if (!needsInput && !needsCost) return {
		model,
		mutated: false
	};
	const filled = { ...model };
	if (needsInput) filled.input = ["text"];
	if (needsCost) filled.cost = {
		input: model.cost?.input ?? 0,
		output: model.cost?.output ?? 0,
		cacheRead: model.cost?.cacheRead ?? 0,
		cacheWrite: model.cost?.cacheWrite ?? 0
	};
	return {
		model: filled,
		mutated: true
	};
}
function defaultFillProviderModels(provider) {
	if (!Array.isArray(provider.models) || provider.models.length === 0) return {
		provider,
		mutated: false
	};
	let anyChange = false;
	const nextModels = provider.models.map((m) => {
		const { model, mutated } = defaultFillModelDefinition(m);
		if (mutated) anyChange = true;
		return model;
	});
	if (!anyChange) return {
		provider,
		mutated: false
	};
	return {
		provider: {
			...provider,
			models: nextModels
		},
		mutated: true
	};
}
/**
* Auto-fill `compat` for self-hosted CoreWeave deployments (vLLM and SGLang
* both live behind `*.coreweave.app/v1` URLs).
*
* Background: pi-ai's auto-detection in providers/openai-completions.js
* treats unknown baseUrls as "standard OpenAI" — which means
* `supportsDeveloperRole: true` and `maxTokensField: "max_completion_tokens"`.
* SGLang rejects both with `400 "Unexpected message role."` (developer role)
* or `400 "Field not allowed"` (max_completion_tokens). vLLM accepts both
* variants but doesn't actually need them — the SGLang-compatible defaults
* are a strict subset of what vLLM also accepts.
*
* Result: applying these settings to ANY `coreweave.app` URL is safe (vLLM
* keeps working, SGLang stops rejecting), and turns a silent footgun into
* a no-config experience for fresh installs that copy a vLLM provider
* definition for an SGLang deployment. Per-model `compat` overrides win
* (we only fill when the field is absent).
*
* Net change for users: zero on existing setups that already work; a
* working endpoint instead of opaque 400s on Qwen 3.6 / future SGLang
* deployments. Master doc §11.6 documents the matrix this implements.
*/
function defaultFillCoreweaveCompat(provider) {
	if (!Array.isArray(provider.models) || provider.models.length === 0) return {
		provider,
		mutated: false
	};
	if (!(typeof provider.baseUrl === "string" ? provider.baseUrl : "").includes("coreweave.app")) return {
		provider,
		mutated: false
	};
	let anyChange = false;
	const nextModels = provider.models.map((m) => {
		if (m.compat && typeof m.compat === "object") return m;
		anyChange = true;
		return {
			...m,
			compat: {
				supportsDeveloperRole: false,
				maxTokensField: "max_tokens",
				supportsStore: false
			}
		};
	});
	if (!anyChange) return {
		provider,
		mutated: false
	};
	return {
		provider: {
			...provider,
			models: nextModels
		},
		mutated: true
	};
}
function normalizeProviders(params) {
	const { providers } = params;
	if (!providers) return providers;
	const authStore = ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false });
	let mutated = false;
	const next = {};
	for (const [key, provider] of Object.entries(providers)) {
		const normalizedKey = key.trim();
		let normalizedProvider = provider;
		{
			const filled = defaultFillProviderModels(normalizedProvider);
			if (filled.mutated) {
				mutated = true;
				normalizedProvider = filled.provider;
			}
		}
		{
			const filled = defaultFillCoreweaveCompat(normalizedProvider);
			if (filled.mutated) {
				mutated = true;
				normalizedProvider = filled.provider;
			}
		}
		if (normalizedProvider.apiKey && normalizeApiKeyConfig(normalizedProvider.apiKey) !== normalizedProvider.apiKey) {
			mutated = true;
			normalizedProvider = {
				...normalizedProvider,
				apiKey: normalizeApiKeyConfig(normalizedProvider.apiKey)
			};
		}
		if (Array.isArray(normalizedProvider.models) && normalizedProvider.models.length > 0 && !normalizedProvider.apiKey?.trim()) if ((normalizedProvider.auth ?? (normalizedKey === "amazon-bedrock" ? "aws-sdk" : void 0)) === "aws-sdk") {
			const apiKey = resolveAwsSdkApiKeyVarName();
			mutated = true;
			normalizedProvider = {
				...normalizedProvider,
				apiKey
			};
		} else {
			const fromEnv = resolveEnvApiKeyVarName(normalizedKey);
			const fromProfiles = resolveApiKeyFromProfiles({
				provider: normalizedKey,
				store: authStore
			});
			const apiKey = fromEnv ?? fromProfiles;
			if (apiKey?.trim()) {
				mutated = true;
				normalizedProvider = {
					...normalizedProvider,
					apiKey
				};
			}
		}
		if (normalizedKey === "google") {
			const googleNormalized = normalizeGoogleProvider(normalizedProvider);
			if (googleNormalized !== normalizedProvider) mutated = true;
			normalizedProvider = googleNormalized;
		}
		next[key] = normalizedProvider;
	}
	return mutated ? next : providers;
}
function buildMinimaxProvider() {
	return {
		baseUrl: MINIMAX_PORTAL_BASE_URL,
		api: "anthropic-messages",
		models: [
			buildMinimaxTextModel({
				id: MINIMAX_DEFAULT_MODEL_ID,
				name: "MiniMax M2.1",
				reasoning: false
			}),
			buildMinimaxTextModel({
				id: "MiniMax-M2.1-lightning",
				name: "MiniMax M2.1 Lightning",
				reasoning: false
			}),
			buildMinimaxModel({
				id: MINIMAX_DEFAULT_VISION_MODEL_ID,
				name: "MiniMax VL 01",
				reasoning: false,
				input: ["text", "image"]
			}),
			buildMinimaxTextModel({
				id: "MiniMax-M2.5",
				name: "MiniMax M2.5",
				reasoning: true
			}),
			buildMinimaxTextModel({
				id: "MiniMax-M2.5-Lightning",
				name: "MiniMax M2.5 Lightning",
				reasoning: true
			})
		]
	};
}
function buildMinimaxPortalProvider() {
	return {
		baseUrl: MINIMAX_PORTAL_BASE_URL,
		api: "anthropic-messages",
		models: [buildMinimaxTextModel({
			id: MINIMAX_DEFAULT_MODEL_ID,
			name: "MiniMax M2.1",
			reasoning: false
		}), buildMinimaxTextModel({
			id: "MiniMax-M2.5",
			name: "MiniMax M2.5",
			reasoning: true
		})]
	};
}
function buildMoonshotProvider() {
	return {
		baseUrl: MOONSHOT_BASE_URL,
		api: "openai-completions",
		models: [{
			id: MOONSHOT_DEFAULT_MODEL_ID,
			name: "Kimi K2.5",
			reasoning: false,
			input: ["text"],
			cost: MOONSHOT_DEFAULT_COST,
			contextWindow: MOONSHOT_DEFAULT_CONTEXT_WINDOW,
			maxTokens: MOONSHOT_DEFAULT_MAX_TOKENS
		}]
	};
}
function buildKimiCodingProvider() {
	return {
		baseUrl: KIMI_CODING_BASE_URL,
		api: "anthropic-messages",
		models: [{
			id: KIMI_CODING_DEFAULT_MODEL_ID,
			name: "Kimi for Coding",
			reasoning: true,
			input: ["text", "image"],
			cost: KIMI_CODING_DEFAULT_COST,
			contextWindow: KIMI_CODING_DEFAULT_CONTEXT_WINDOW,
			maxTokens: KIMI_CODING_DEFAULT_MAX_TOKENS
		}]
	};
}
function buildQwenPortalProvider() {
	return {
		baseUrl: QWEN_PORTAL_BASE_URL,
		api: "openai-completions",
		models: [{
			id: "coder-model",
			name: "Qwen Coder",
			reasoning: false,
			input: ["text"],
			cost: QWEN_PORTAL_DEFAULT_COST,
			contextWindow: QWEN_PORTAL_DEFAULT_CONTEXT_WINDOW,
			maxTokens: QWEN_PORTAL_DEFAULT_MAX_TOKENS
		}, {
			id: "vision-model",
			name: "Qwen Vision",
			reasoning: false,
			input: ["text", "image"],
			cost: QWEN_PORTAL_DEFAULT_COST,
			contextWindow: QWEN_PORTAL_DEFAULT_CONTEXT_WINDOW,
			maxTokens: QWEN_PORTAL_DEFAULT_MAX_TOKENS
		}]
	};
}
function buildSyntheticProvider() {
	return {
		baseUrl: SYNTHETIC_BASE_URL,
		api: "anthropic-messages",
		models: SYNTHETIC_MODEL_CATALOG.map(buildSyntheticModelDefinition)
	};
}
function buildDoubaoProvider() {
	return {
		baseUrl: DOUBAO_BASE_URL,
		api: "openai-completions",
		models: DOUBAO_MODEL_CATALOG.map(buildDoubaoModelDefinition)
	};
}
function buildDoubaoCodingProvider() {
	return {
		baseUrl: DOUBAO_CODING_BASE_URL,
		api: "openai-completions",
		models: DOUBAO_CODING_MODEL_CATALOG.map(buildDoubaoModelDefinition)
	};
}
function buildBytePlusProvider() {
	return {
		baseUrl: BYTEPLUS_BASE_URL,
		api: "openai-completions",
		models: BYTEPLUS_MODEL_CATALOG.map(buildBytePlusModelDefinition)
	};
}
function buildBytePlusCodingProvider() {
	return {
		baseUrl: BYTEPLUS_CODING_BASE_URL,
		api: "openai-completions",
		models: BYTEPLUS_CODING_MODEL_CATALOG.map(buildBytePlusModelDefinition)
	};
}
function buildXiaomiProvider() {
	return {
		baseUrl: XIAOMI_BASE_URL,
		api: "anthropic-messages",
		models: [{
			id: XIAOMI_DEFAULT_MODEL_ID,
			name: "Xiaomi MiMo V2 Flash",
			reasoning: false,
			input: ["text"],
			cost: XIAOMI_DEFAULT_COST,
			contextWindow: XIAOMI_DEFAULT_CONTEXT_WINDOW,
			maxTokens: XIAOMI_DEFAULT_MAX_TOKENS
		}]
	};
}
async function buildVeniceProvider() {
	return {
		baseUrl: VENICE_BASE_URL,
		api: "openai-completions",
		models: await discoverVeniceModels()
	};
}
async function buildOllamaProvider(configuredBaseUrl) {
	const models = await discoverOllamaModels(configuredBaseUrl);
	return {
		baseUrl: resolveOllamaApiBase(configuredBaseUrl),
		api: "ollama",
		models
	};
}
async function buildHuggingfaceProvider(apiKey) {
	const resolvedSecret = apiKey?.trim() !== "" ? /^[A-Z][A-Z0-9_]*$/.test(apiKey.trim()) ? (process.env[apiKey.trim()] ?? "").trim() : apiKey.trim() : "";
	return {
		baseUrl: HUGGINGFACE_BASE_URL,
		api: "openai-completions",
		models: resolvedSecret !== "" ? await discoverHuggingfaceModels(resolvedSecret) : HUGGINGFACE_MODEL_CATALOG.map(buildHuggingfaceModelDefinition)
	};
}
function buildTogetherProvider() {
	return {
		baseUrl: TOGETHER_BASE_URL,
		api: "openai-completions",
		models: TOGETHER_MODEL_CATALOG.map(buildTogetherModelDefinition)
	};
}
async function buildVllmProvider(params) {
	const baseUrl = (params?.baseUrl?.trim() || VLLM_BASE_URL).replace(/\/+$/, "");
	return {
		baseUrl,
		api: "openai-completions",
		models: await discoverVllmModels(baseUrl, params?.apiKey)
	};
}
function buildQianfanProvider() {
	return {
		baseUrl: QIANFAN_BASE_URL,
		api: "openai-completions",
		models: [{
			id: QIANFAN_DEFAULT_MODEL_ID,
			name: "DEEPSEEK V3.2",
			reasoning: true,
			input: ["text"],
			cost: QIANFAN_DEFAULT_COST,
			contextWindow: QIANFAN_DEFAULT_CONTEXT_WINDOW,
			maxTokens: QIANFAN_DEFAULT_MAX_TOKENS
		}, {
			id: "ernie-5.0-thinking-preview",
			name: "ERNIE-5.0-Thinking-Preview",
			reasoning: true,
			input: ["text", "image"],
			cost: QIANFAN_DEFAULT_COST,
			contextWindow: 119e3,
			maxTokens: 64e3
		}]
	};
}
function buildNvidiaProvider() {
	return {
		baseUrl: NVIDIA_BASE_URL,
		api: "openai-completions",
		models: [
			{
				id: NVIDIA_DEFAULT_MODEL_ID,
				name: "NVIDIA Llama 3.1 Nemotron 70B Instruct",
				reasoning: false,
				input: ["text"],
				cost: NVIDIA_DEFAULT_COST,
				contextWindow: NVIDIA_DEFAULT_CONTEXT_WINDOW,
				maxTokens: NVIDIA_DEFAULT_MAX_TOKENS
			},
			{
				id: "meta/llama-3.3-70b-instruct",
				name: "Meta Llama 3.3 70B Instruct",
				reasoning: false,
				input: ["text"],
				cost: NVIDIA_DEFAULT_COST,
				contextWindow: 131072,
				maxTokens: 4096
			},
			{
				id: "nvidia/mistral-nemo-minitron-8b-8k-instruct",
				name: "NVIDIA Mistral NeMo Minitron 8B Instruct",
				reasoning: false,
				input: ["text"],
				cost: NVIDIA_DEFAULT_COST,
				contextWindow: 8192,
				maxTokens: 2048
			}
		]
	};
}
async function resolveImplicitProviders(params) {
	const providers = {};
	const authStore = ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false });
	const minimaxKey = resolveEnvApiKeyVarName("minimax") ?? resolveApiKeyFromProfiles({
		provider: "minimax",
		store: authStore
	});
	if (minimaxKey) providers.minimax = {
		...buildMinimaxProvider(),
		apiKey: minimaxKey
	};
	if (listProfilesForProvider(authStore, "minimax-portal").length > 0) providers["minimax-portal"] = {
		...buildMinimaxPortalProvider(),
		apiKey: MINIMAX_OAUTH_PLACEHOLDER
	};
	const moonshotKey = resolveEnvApiKeyVarName("moonshot") ?? resolveApiKeyFromProfiles({
		provider: "moonshot",
		store: authStore
	});
	if (moonshotKey) providers.moonshot = {
		...buildMoonshotProvider(),
		apiKey: moonshotKey
	};
	const kimiCodingKey = resolveEnvApiKeyVarName("kimi-coding") ?? resolveApiKeyFromProfiles({
		provider: "kimi-coding",
		store: authStore
	});
	if (kimiCodingKey) providers["kimi-coding"] = {
		...buildKimiCodingProvider(),
		apiKey: kimiCodingKey
	};
	const syntheticKey = resolveEnvApiKeyVarName("synthetic") ?? resolveApiKeyFromProfiles({
		provider: "synthetic",
		store: authStore
	});
	if (syntheticKey) providers.synthetic = {
		...buildSyntheticProvider(),
		apiKey: syntheticKey
	};
	const veniceKey = resolveEnvApiKeyVarName("venice") ?? resolveApiKeyFromProfiles({
		provider: "venice",
		store: authStore
	});
	if (veniceKey) providers.venice = {
		...await buildVeniceProvider(),
		apiKey: veniceKey
	};
	if (listProfilesForProvider(authStore, "qwen-portal").length > 0) providers["qwen-portal"] = {
		...buildQwenPortalProvider(),
		apiKey: QWEN_PORTAL_OAUTH_PLACEHOLDER
	};
	const volcengineKey = resolveEnvApiKeyVarName("volcengine") ?? resolveApiKeyFromProfiles({
		provider: "volcengine",
		store: authStore
	});
	if (volcengineKey) {
		providers.volcengine = {
			...buildDoubaoProvider(),
			apiKey: volcengineKey
		};
		providers["volcengine-plan"] = {
			...buildDoubaoCodingProvider(),
			apiKey: volcengineKey
		};
	}
	const byteplusKey = resolveEnvApiKeyVarName("byteplus") ?? resolveApiKeyFromProfiles({
		provider: "byteplus",
		store: authStore
	});
	if (byteplusKey) {
		providers.byteplus = {
			...buildBytePlusProvider(),
			apiKey: byteplusKey
		};
		providers["byteplus-plan"] = {
			...buildBytePlusCodingProvider(),
			apiKey: byteplusKey
		};
	}
	const xiaomiKey = resolveEnvApiKeyVarName("xiaomi") ?? resolveApiKeyFromProfiles({
		provider: "xiaomi",
		store: authStore
	});
	if (xiaomiKey) providers.xiaomi = {
		...buildXiaomiProvider(),
		apiKey: xiaomiKey
	};
	const cloudflareProfiles = listProfilesForProvider(authStore, "cloudflare-ai-gateway");
	for (const profileId of cloudflareProfiles) {
		const cred = authStore.profiles[profileId];
		if (cred?.type !== "api_key") continue;
		const accountId = cred.metadata?.accountId?.trim();
		const gatewayId = cred.metadata?.gatewayId?.trim();
		if (!accountId || !gatewayId) continue;
		const baseUrl = resolveCloudflareAiGatewayBaseUrl({
			accountId,
			gatewayId
		});
		if (!baseUrl) continue;
		const apiKey = resolveEnvApiKeyVarName("cloudflare-ai-gateway") ?? cred.key?.trim() ?? "";
		if (!apiKey) continue;
		providers["cloudflare-ai-gateway"] = {
			baseUrl,
			api: "anthropic-messages",
			apiKey,
			models: [buildCloudflareAiGatewayModelDefinition()]
		};
		break;
	}
	const ollamaKey = resolveEnvApiKeyVarName("ollama") ?? resolveApiKeyFromProfiles({
		provider: "ollama",
		store: authStore
	});
	if (ollamaKey) {
		const ollamaBaseUrl = params.explicitProviders?.ollama?.baseUrl;
		providers.ollama = {
			...await buildOllamaProvider(ollamaBaseUrl),
			apiKey: ollamaKey
		};
	}
	if (!params.explicitProviders?.vllm) {
		const vllmEnvVar = resolveEnvApiKeyVarName("vllm");
		const vllmProfileKey = resolveApiKeyFromProfiles({
			provider: "vllm",
			store: authStore
		});
		const vllmKey = vllmEnvVar ?? vllmProfileKey;
		if (vllmKey) providers.vllm = {
			...await buildVllmProvider({ apiKey: (vllmEnvVar ? process.env[vllmEnvVar]?.trim() ?? "" : vllmProfileKey ?? "") || void 0 }),
			apiKey: vllmKey
		};
	}
	const togetherKey = resolveEnvApiKeyVarName("together") ?? resolveApiKeyFromProfiles({
		provider: "together",
		store: authStore
	});
	if (togetherKey) providers.together = {
		...buildTogetherProvider(),
		apiKey: togetherKey
	};
	const huggingfaceKey = resolveEnvApiKeyVarName("huggingface") ?? resolveApiKeyFromProfiles({
		provider: "huggingface",
		store: authStore
	});
	if (huggingfaceKey) providers.huggingface = {
		...await buildHuggingfaceProvider(huggingfaceKey),
		apiKey: huggingfaceKey
	};
	const qianfanKey = resolveEnvApiKeyVarName("qianfan") ?? resolveApiKeyFromProfiles({
		provider: "qianfan",
		store: authStore
	});
	if (qianfanKey) providers.qianfan = {
		...buildQianfanProvider(),
		apiKey: qianfanKey
	};
	const nvidiaKey = resolveEnvApiKeyVarName("nvidia") ?? resolveApiKeyFromProfiles({
		provider: "nvidia",
		store: authStore
	});
	if (nvidiaKey) providers.nvidia = {
		...buildNvidiaProvider(),
		apiKey: nvidiaKey
	};
	return providers;
}
async function resolveImplicitCopilotProvider(params) {
	const env = params.env ?? process.env;
	const authStore = ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false });
	const hasProfile = listProfilesForProvider(authStore, "github-copilot").length > 0;
	const githubToken = (env.COPILOT_GITHUB_TOKEN ?? env.GH_TOKEN ?? env.GITHUB_TOKEN ?? "").trim();
	if (!hasProfile && !githubToken) return null;
	let selectedGithubToken = githubToken;
	if (!selectedGithubToken && hasProfile) {
		const profileId = listProfilesForProvider(authStore, "github-copilot")[0];
		const profile = profileId ? authStore.profiles[profileId] : void 0;
		if (profile && profile.type === "token") selectedGithubToken = profile.token;
	}
	let baseUrl = DEFAULT_COPILOT_API_BASE_URL;
	if (selectedGithubToken) try {
		baseUrl = (await resolveCopilotApiToken({
			githubToken: selectedGithubToken,
			env
		})).baseUrl;
	} catch {
		baseUrl = DEFAULT_COPILOT_API_BASE_URL;
	}
	return {
		baseUrl,
		models: []
	};
}
async function resolveImplicitBedrockProvider(params) {
	const env = params.env ?? process.env;
	const discoveryConfig = params.config?.models?.bedrockDiscovery;
	const enabled = discoveryConfig?.enabled;
	const hasAwsCreds = resolveAwsSdkEnvVarName(env) !== void 0;
	if (enabled === false) return null;
	if (enabled !== true && !hasAwsCreds) return null;
	const region = discoveryConfig?.region ?? env.AWS_REGION ?? env.AWS_DEFAULT_REGION ?? "us-east-1";
	const models = await discoverBedrockModels({
		region,
		config: discoveryConfig
	});
	if (models.length === 0) return null;
	return {
		baseUrl: `https://bedrock-runtime.${region}.amazonaws.com`,
		api: "bedrock-converse-stream",
		auth: "aws-sdk",
		models
	};
}

//#endregion
//#region src/agents/models-config.ts
const DEFAULT_MODE = "merge";
function mergeProviderModels(implicit, explicit) {
	const implicitModels = Array.isArray(implicit.models) ? implicit.models : [];
	const explicitModels = Array.isArray(explicit.models) ? explicit.models : [];
	if (implicitModels.length === 0) return {
		...implicit,
		...explicit
	};
	const getId = (model) => {
		if (!model || typeof model !== "object") return "";
		const id = model.id;
		return typeof id === "string" ? id.trim() : "";
	};
	const seen = new Set(explicitModels.map(getId).filter(Boolean));
	const mergedModels = [...explicitModels, ...implicitModels.filter((model) => {
		const id = getId(model);
		if (!id) return false;
		if (seen.has(id)) return false;
		seen.add(id);
		return true;
	})];
	return {
		...implicit,
		...explicit,
		models: mergedModels
	};
}
function mergeProviders(params) {
	const out = params.implicit ? { ...params.implicit } : {};
	for (const [key, explicit] of Object.entries(params.explicit ?? {})) {
		const providerKey = key.trim();
		if (!providerKey) continue;
		const implicit = out[providerKey];
		out[providerKey] = implicit ? mergeProviderModels(implicit, explicit) : explicit;
	}
	return out;
}
async function readJson(pathname) {
	try {
		const raw = await fs.readFile(pathname, "utf8");
		return JSON.parse(raw);
	} catch {
		return null;
	}
}
async function ensureSymiModelsJson(config, agentDirOverride) {
	const cfg = config ?? loadConfig();
	const agentDir = agentDirOverride?.trim() ? agentDirOverride.trim() : resolveSymiAgentDir();
	const explicitProviders = cfg.models?.providers ?? {};
	const providers = mergeProviders({
		implicit: await resolveImplicitProviders({
			agentDir,
			explicitProviders
		}),
		explicit: explicitProviders
	});
	const implicitBedrock = await resolveImplicitBedrockProvider({
		agentDir,
		config: cfg
	});
	if (implicitBedrock) {
		const existing = providers["amazon-bedrock"];
		providers["amazon-bedrock"] = existing ? mergeProviderModels(implicitBedrock, existing) : implicitBedrock;
	}
	const implicitCopilot = await resolveImplicitCopilotProvider({ agentDir });
	if (implicitCopilot && !providers["github-copilot"]) providers["github-copilot"] = implicitCopilot;
	if (Object.keys(providers).length === 0) return {
		agentDir,
		wrote: false
	};
	const mode = cfg.models?.mode ?? DEFAULT_MODE;
	const targetPath = path.join(agentDir, "models.json");
	let mergedProviders = providers;
	let existingRaw = "";
	if (mode === "merge") {
		const existing = await readJson(targetPath);
		if (isRecord(existing) && isRecord(existing.providers)) mergedProviders = {
			...existing.providers,
			...providers
		};
	}
	const normalizedProviders = normalizeProviders({
		providers: mergedProviders,
		agentDir
	});
	const next = `${JSON.stringify({ providers: normalizedProviders }, null, 2)}\n`;
	try {
		existingRaw = await fs.readFile(targetPath, "utf8");
	} catch {
		existingRaw = "";
	}
	if (existingRaw === next) return {
		agentDir,
		wrote: false
	};
	await fs.mkdir(agentDir, {
		recursive: true,
		mode: 448
	});
	await fs.writeFile(targetPath, next, { mode: 384 });
	return {
		agentDir,
		wrote: true
	};
}

//#endregion
export { HUGGINGFACE_MODEL_CATALOG as C, CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF as D, isHuggingfacePolicyLocked as E, buildCloudflareAiGatewayModelDefinition as O, HUGGINGFACE_BASE_URL as S, discoverHuggingfaceModels as T, SYNTHETIC_DEFAULT_MODEL_REF as _, buildKimiCodingProvider as a, OLLAMA_NATIVE_BASE_URL as b, normalizeGoogleModelId as c, VENICE_MODEL_CATALOG as d, buildVeniceModelDefinition as f, SYNTHETIC_BASE_URL as g, buildTogetherModelDefinition as h, XIAOMI_DEFAULT_MODEL_ID as i, resolveCloudflareAiGatewayBaseUrl as k, VENICE_BASE_URL as l, TOGETHER_MODEL_CATALOG as m, QIANFAN_BASE_URL as n, buildQianfanProvider as o, TOGETHER_BASE_URL as p, QIANFAN_DEFAULT_MODEL_ID as r, buildXiaomiProvider as s, ensureSymiModelsJson as t, VENICE_DEFAULT_MODEL_REF as u, SYNTHETIC_MODEL_CATALOG as v, buildHuggingfaceModelDefinition as w, createOllamaStreamFn as x, buildSyntheticModelDefinition as y };