import { H as isCacheEnabled, T as OpenAiChatCompletionProvider, V as getCache, gt as invariant, h as OpenAiCompletionProvider, mt as logger_default, x as OpenAiEmbeddingProvider, yt as getEnvString } from "./server/index.js";
import fs from "fs";
import path from "path";
import dedent from "dedent";
import crypto from "crypto";

//#region src/providers/agentic-utils.ts
/**
* Shared utilities for agentic providers (Claude Agent SDK, OpenCode SDK, etc.)
*
* These utilities handle common functionality needed by coding agent providers:
* - Working directory fingerprinting for cache key generation
* - Response caching with fingerprint support
*/
/**
* Timeout for working directory fingerprint generation (ms)
* Prevents hanging on extremely large directories
*/
const FINGERPRINT_TIMEOUT_MS = 2e3;
/**
* Get a fingerprint for a working directory to use as a cache key.
* Checks directory mtime and descendant file mtimes recursively.
*
* This allows for caching prompts that use the same working directory
* when the files haven't changed.
*
* @param workingDir - Absolute path to the working directory
* @returns SHA-256 hash fingerprint of the directory state
* @throws Error if fingerprinting times out or directory is inaccessible
*/
async function getWorkingDirFingerprint(workingDir) {
	const dirMtime = fs.statSync(workingDir).mtimeMs;
	const startTime = Date.now();
	const getAllFiles = (dir, files = []) => {
		if (Date.now() - startTime > FINGERPRINT_TIMEOUT_MS) throw new Error("Working directory fingerprint timed out");
		const entries = fs.readdirSync(dir, { withFileTypes: true });
		for (const entry of entries) {
			const fullPath = path.join(dir, entry.name);
			if (entry.isDirectory()) getAllFiles(fullPath, files);
			else if (entry.isFile()) files.push(fullPath);
		}
		return files;
	};
	const fingerprintData = `dir:${dirMtime};files:${getAllFiles(workingDir).map((file) => {
		const stat = fs.statSync(file);
		return `${path.relative(workingDir, file)}:${stat.mtimeMs}`;
	}).sort().join(",")}`;
	return crypto.createHash("sha256").update(fingerprintData).digest("hex");
}
/**
* Generate a cache key from arbitrary data using SHA-256 hash
*
* @param prefix - Cache key prefix (provider identifier)
* @param data - Data to hash for the cache key
* @returns Prefixed SHA-256 hash cache key
*/
function generateCacheKey(prefix, data) {
	const stringified = JSON.stringify(data);
	return `${prefix}:${crypto.createHash("sha256").update(stringified).digest("hex")}`;
}
/**
* Initialize cache and check for cached response
*
* This handles the common caching pattern used by agentic providers:
* 1. Check if caching is enabled
* 2. Generate working directory fingerprint if needed
* 3. Generate cache key
* 4. Return cache configuration for use by the provider
*
* @param options - Cache options including prefix and working directory
* @param cacheKeyData - Data to include in the cache key
* @returns Cache configuration and optional cached response
*/
async function initializeAgenticCache(options, cacheKeyData) {
	if (!isCacheEnabled()) return {
		shouldCache: false,
		shouldReadCache: false,
		shouldWriteCache: false
	};
	let workingDirFingerprint = null;
	if (options.workingDir) try {
		workingDirFingerprint = await getWorkingDirFingerprint(options.workingDir);
	} catch (error) {
		logger_default.error(dedent`Error getting working directory fingerprint for cache key - ${options.workingDir}: ${String(error)}

        Caching is disabled.`);
		return {
			shouldCache: false,
			shouldReadCache: false,
			shouldWriteCache: false
		};
	}
	const cache = await getCache();
	const cacheKey = generateCacheKey(options.cacheKeyPrefix, {
		...cacheKeyData,
		workingDirFingerprint
	});
	return {
		shouldCache: true,
		shouldReadCache: !options.bustCache,
		shouldWriteCache: true,
		cache,
		cacheKey,
		workingDirFingerprint
	};
}
/**
* Try to get a cached response
*
* @param cacheResult - Result from initializeAgenticCache
* @param debugContext - Context for debug logging (e.g., prompt preview)
* @returns Cached ProviderResponse if found, undefined otherwise
*/
async function getCachedResponse(cacheResult, debugContext) {
	if (!cacheResult.shouldReadCache || !cacheResult.cache || !cacheResult.cacheKey) return;
	try {
		const cachedResponse = await cacheResult.cache.get(cacheResult.cacheKey);
		if (cachedResponse) {
			logger_default.debug(`Returning cached response${debugContext ? ` for ${debugContext}` : ""} (cache key: ${cacheResult.cacheKey})`);
			return {
				...JSON.parse(cachedResponse),
				cached: true
			};
		}
	} catch (error) {
		logger_default.error(`Error getting cached response: ${String(error)}`);
	}
}
/**
* Cache a provider response
*
* @param cacheResult - Result from initializeAgenticCache
* @param response - The ProviderResponse to cache
* @param debugContext - Context for debug logging
*/
async function cacheResponse(cacheResult, response, debugContext) {
	if (!cacheResult.shouldWriteCache || !cacheResult.cache || !cacheResult.cacheKey) return;
	try {
		await cacheResult.cache.set(cacheResult.cacheKey, JSON.stringify(response));
	} catch (error) {
		logger_default.error(`Error caching response${debugContext ? ` for ${debugContext}` : ""}: ${String(error)}`);
	}
}

//#endregion
//#region src/providers/cloudflare-ai.ts
function getCloudflareApiConfig(config, env) {
	const apiTokenCandidate = config?.apiKey || (config?.apiKeyEnvar ? getEnvString(config.apiKeyEnvar) || env?.[config.apiKeyEnvar] : void 0) || env?.CLOUDFLARE_API_KEY || getEnvString("CLOUDFLARE_API_KEY");
	invariant(apiTokenCandidate, "Cloudflare API token required. Supply it via config apiKey or apiKeyEnvar, or the CLOUDFLARE_API_KEY environment variable");
	const accountIdCandidate = config?.accountId || (config?.accountIdEnvar ? getEnvString(config.accountIdEnvar) || env?.[config.accountIdEnvar] : void 0) || env?.CLOUDFLARE_ACCOUNT_ID || getEnvString("CLOUDFLARE_ACCOUNT_ID");
	invariant(accountIdCandidate, "Cloudflare account ID required. Supply it via config accountId or accountIdEnvar, or the CLOUDFLARE_ACCOUNT_ID environment variable");
	return {
		apiToken: apiTokenCandidate,
		accountId: accountIdCandidate
	};
}
function getApiBaseUrl(config, env) {
	if (config?.apiBaseUrl) return config.apiBaseUrl;
	const { accountId } = getCloudflareApiConfig(config, env);
	return `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/v1`;
}
function getPassthroughConfig(config) {
	const { accountId: _accountId, accountIdEnvar: _accountIdEnvar, apiKey: _apiKey, apiKeyEnvar: _apiKeyEnvar, apiBaseUrl: _apiBaseUrl, ...passthrough } = config || {};
	return passthrough;
}
var CloudflareAiChatCompletionProvider = class extends OpenAiChatCompletionProvider {
	cloudflareConfig;
	modelType = "chat";
	constructor(modelName, providerOptions) {
		const apiBaseUrl = getApiBaseUrl(providerOptions.config, providerOptions.env);
		const passthrough = getPassthroughConfig(providerOptions.config);
		const config = {
			...providerOptions.config,
			apiKeyEnvar: "CLOUDFLARE_API_KEY",
			apiBaseUrl,
			passthrough
		};
		super(modelName, {
			...providerOptions,
			config
		});
		this.cloudflareConfig = providerOptions.config || {};
	}
	id() {
		return `cloudflare-ai:${this.modelType}:${this.modelName}`;
	}
	toString() {
		return `[Cloudflare AI ${this.modelType} Provider ${this.modelName}]`;
	}
	getApiKey() {
		const { apiToken } = getCloudflareApiConfig(this.cloudflareConfig, this.env);
		return apiToken;
	}
	toJSON() {
		return {
			provider: "cloudflare-ai",
			model: this.modelName,
			modelType: this.modelType,
			config: {
				...this.config,
				...this.getApiKey() && { apiKey: void 0 }
			}
		};
	}
};
var CloudflareAiCompletionProvider = class extends OpenAiCompletionProvider {
	cloudflareConfig;
	modelType = "completion";
	constructor(modelName, providerOptions) {
		const apiBaseUrl = getApiBaseUrl(providerOptions.config, providerOptions.env);
		const passthrough = getPassthroughConfig(providerOptions.config);
		const config = {
			...providerOptions.config,
			apiKeyEnvar: "CLOUDFLARE_API_KEY",
			apiBaseUrl,
			passthrough
		};
		super(modelName, {
			...providerOptions,
			config
		});
		this.cloudflareConfig = providerOptions.config || {};
	}
	id() {
		return `cloudflare-ai:${this.modelType}:${this.modelName}`;
	}
	toString() {
		return `[Cloudflare AI ${this.modelType} Provider ${this.modelName}]`;
	}
	getApiKey() {
		const { apiToken } = getCloudflareApiConfig(this.cloudflareConfig, this.env);
		return apiToken;
	}
	toJSON() {
		return {
			provider: "cloudflare-ai",
			model: this.modelName,
			modelType: this.modelType,
			config: {
				...this.config,
				...this.getApiKey() && { apiKey: void 0 }
			}
		};
	}
};
var CloudflareAiEmbeddingProvider = class extends OpenAiEmbeddingProvider {
	cloudflareConfig;
	modelType = "embedding";
	constructor(modelName, providerOptions) {
		const apiBaseUrl = getApiBaseUrl(providerOptions.config, providerOptions.env);
		const passthrough = getPassthroughConfig(providerOptions.config);
		const config = {
			...providerOptions.config,
			apiKeyEnvar: "CLOUDFLARE_API_KEY",
			apiBaseUrl,
			passthrough
		};
		super(modelName, {
			...providerOptions,
			config
		});
		this.cloudflareConfig = providerOptions.config || {};
	}
	id() {
		return `cloudflare-ai:${this.modelType}:${this.modelName}`;
	}
	toString() {
		return `[Cloudflare AI ${this.modelType} Provider ${this.modelName}]`;
	}
	getApiKey() {
		const { apiToken } = getCloudflareApiConfig(this.cloudflareConfig, this.env);
		return apiToken;
	}
	toJSON() {
		return {
			provider: "cloudflare-ai",
			model: this.modelName,
			modelType: this.modelType,
			config: {
				...this.config,
				...this.getApiKey() && { apiKey: void 0 }
			}
		};
	}
};
function createCloudflareAiProvider(providerPath, options = {}) {
	const splits = providerPath.split(":");
	const modelType = splits[1];
	const modelName = splits.slice(2).join(":");
	invariant(modelName, "Model name is required");
	switch (modelType) {
		case "chat": return new CloudflareAiChatCompletionProvider(modelName, options);
		case "completion": return new CloudflareAiCompletionProvider(modelName, options);
		case "embedding":
		case "embeddings": return new CloudflareAiEmbeddingProvider(modelName, options);
		default: throw new Error(`Unknown Cloudflare AI model type: ${modelType}`);
	}
}

//#endregion
export { createCloudflareAiProvider, getCachedResponse as n, initializeAgenticCache as r, cacheResponse as t };
//# sourceMappingURL=cloudflare-ai-B2y3pBsy.js.map