import { m as resolveUserPath } from "./utils-3Lue6wVm.js";
import { s as resolveAgentWorkspaceDir } from "./agent-scope-u760_XKU.js";
import { t as parseDurationMs } from "./parse-duration-Y7ul2bkb.js";
import fs from "node:fs";
import path from "node:path";
import os from "node:os";

//#region ../../src/utils/shell-argv.ts
function splitShellArgs(raw) {
	const tokens = [];
	let buf = "";
	let inSingle = false;
	let inDouble = false;
	let escaped = false;
	const pushToken = () => {
		if (buf.length > 0) {
			tokens.push(buf);
			buf = "";
		}
	};
	for (let i = 0; i < raw.length; i += 1) {
		const ch = raw[i];
		if (escaped) {
			buf += ch;
			escaped = false;
			continue;
		}
		if (!inSingle && !inDouble && ch === "\\") {
			escaped = true;
			continue;
		}
		if (inSingle) {
			if (ch === "'") inSingle = false;
			else buf += ch;
			continue;
		}
		if (inDouble) {
			if (ch === "\"") inDouble = false;
			else buf += ch;
			continue;
		}
		if (ch === "'") {
			inSingle = true;
			continue;
		}
		if (ch === "\"") {
			inDouble = true;
			continue;
		}
		if (/\s/.test(ch)) {
			pushToken();
			continue;
		}
		buf += ch;
	}
	if (escaped || inSingle || inDouble) return null;
	pushToken();
	return tokens;
}

//#endregion
//#region ../../src/memory/backend-config.ts
const DEFAULT_BACKEND = "qmd";
const DEFAULT_CITATIONS = "auto";
const DEFAULT_QMD_INTERVAL = "5m";
const DEFAULT_QMD_DEBOUNCE_MS = 15e3;
const DEFAULT_QMD_TIMEOUT_MS = 4e3;
const DEFAULT_QMD_EMBED_INTERVAL = "60m";
const DEFAULT_QMD_EMBED_MIN_INTERVAL_MS = 2 * 6e4;
const DEFAULT_QMD_EMBED_MAX_INTERVAL_MS = 30 * 6e4;
const DEFAULT_QMD_EMBED_TOKEN_THRESHOLD = 5e3;
const DEFAULT_QMD_CONSOLIDATE_INTERVAL = "0";
const DEFAULT_QMD_LIMITS = {
	maxResults: 6,
	maxSnippetChars: 700,
	maxInjectedChars: 4e3,
	timeoutMs: DEFAULT_QMD_TIMEOUT_MS
};
const DEFAULT_QMD_SCOPE = {
	default: "deny",
	rules: [{
		action: "allow",
		match: { chatType: "direct" }
	}]
};
function sanitizeName(input) {
	return input.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") || "collection";
}
function ensureUniqueName(base, existing) {
	let name = sanitizeName(base);
	if (!existing.has(name)) {
		existing.add(name);
		return name;
	}
	let suffix = 2;
	while (existing.has(`${name}-${suffix}`)) suffix += 1;
	const unique = `${name}-${suffix}`;
	existing.add(unique);
	return unique;
}
function resolvePath(raw, workspaceDir) {
	const trimmed = raw.trim();
	if (!trimmed) throw new Error("path required");
	if (trimmed.startsWith("~") || path.isAbsolute(trimmed)) return path.normalize(resolveUserPath(trimmed));
	return path.normalize(path.resolve(workspaceDir, trimmed));
}
function isExecutable(filePath) {
	try {
		fs.accessSync(filePath, fs.constants.X_OK);
		return true;
	} catch {
		return false;
	}
}
function resolveExecutablePath(binary, opts) {
	if (!binary || binary.includes(path.sep)) return binary;
	const homeDir = opts?.homeDir ?? os.homedir();
	const pathEntries = (opts?.pathEnv ?? process.env.PATH ?? "").split(path.delimiter).map((entry) => entry.trim()).filter(Boolean);
	const fallbackDirs = [
		path.join(homeDir, ".local", "bin"),
		path.join(homeDir, ".local", "share", "pnpm"),
		path.join(homeDir, ".bun", "bin"),
		path.join(homeDir, ".yarn", "bin"),
		"/opt/homebrew/bin",
		"/usr/local/bin",
		"/usr/bin",
		"/bin"
	];
	const candidates = [...new Set([...pathEntries, ...fallbackDirs])];
	for (const dir of candidates) {
		const candidate = path.join(dir, binary);
		if (isExecutable(candidate)) return candidate;
	}
	return binary;
}
function resolveQmdCommand(rawCommand, opts) {
	return resolveExecutablePath(splitShellArgs(rawCommand)?.[0] || rawCommand.split(/\s+/)[0] || "qmd", opts);
}
function firstNonEmptyString(...values) {
	for (const value of values) {
		if (typeof value !== "string") continue;
		const trimmed = value.trim();
		if (trimmed) return trimmed;
	}
}
function resolveQmdEmbeddingApiKey(cfg) {
	const shadContextConfig = cfg.plugins?.entries?.["shad-context"]?.config;
	const shadContextEmbeddingApiKey = shadContextConfig && typeof shadContextConfig.embeddingApiKey === "string" ? shadContextConfig.embeddingApiKey : void 0;
	const envOpenAiApiKey = typeof cfg.env?.OPENAI_API_KEY === "string" ? cfg.env.OPENAI_API_KEY : void 0;
	return firstNonEmptyString(cfg.memory?.qmd?.embeddingApiKey, shadContextEmbeddingApiKey, cfg.env?.vars?.OPENAI_API_KEY, envOpenAiApiKey, process.env.OPENAI_API_KEY);
}
function resolveIntervalMs(raw) {
	const value = raw?.trim();
	if (!value) return parseDurationMs(DEFAULT_QMD_INTERVAL, { defaultUnit: "m" });
	try {
		return parseDurationMs(value, { defaultUnit: "m" });
	} catch {
		return parseDurationMs(DEFAULT_QMD_INTERVAL, { defaultUnit: "m" });
	}
}
function resolveEmbedIntervalMs(raw) {
	const value = raw?.trim();
	if (!value) return parseDurationMs(DEFAULT_QMD_EMBED_INTERVAL, { defaultUnit: "m" });
	try {
		return parseDurationMs(value, { defaultUnit: "m" });
	} catch {
		return parseDurationMs(DEFAULT_QMD_EMBED_INTERVAL, { defaultUnit: "m" });
	}
}
function resolveConsolidateConfig(raw) {
	const value = raw?.interval?.trim();
	let intervalMs = 0;
	if (value) try {
		intervalMs = parseDurationMs(value, { defaultUnit: "m" });
	} catch {
		intervalMs = parseDurationMs(DEFAULT_QMD_CONSOLIDATE_INTERVAL, { defaultUnit: "m" });
	}
	return {
		intervalMs,
		debounceMs: resolveDebounceMs(raw?.debounceMs),
		onBoot: raw?.onBoot === true
	};
}
function resolveDebounceMs(raw) {
	if (typeof raw === "number" && Number.isFinite(raw) && raw >= 0) return Math.floor(raw);
	return DEFAULT_QMD_DEBOUNCE_MS;
}
function resolveLimits(raw) {
	const parsed = { ...DEFAULT_QMD_LIMITS };
	if (raw?.maxResults && raw.maxResults > 0) parsed.maxResults = Math.floor(raw.maxResults);
	if (raw?.maxSnippetChars && raw.maxSnippetChars > 0) parsed.maxSnippetChars = Math.floor(raw.maxSnippetChars);
	if (raw?.maxInjectedChars && raw.maxInjectedChars > 0) parsed.maxInjectedChars = Math.floor(raw.maxInjectedChars);
	if (raw?.timeoutMs && raw.timeoutMs > 0) parsed.timeoutMs = Math.floor(raw.timeoutMs);
	return parsed;
}
function resolveSessionConfig(cfg, workspaceDir) {
	const enabled = Boolean(cfg?.enabled);
	const exportDirRaw = cfg?.exportDir?.trim();
	return {
		enabled,
		exportDir: exportDirRaw ? resolvePath(exportDirRaw, workspaceDir) : void 0,
		retentionDays: cfg?.retentionDays && cfg.retentionDays > 0 ? Math.floor(cfg.retentionDays) : void 0
	};
}
function resolveCustomPaths(rawPaths, workspaceDir, existing) {
	if (!rawPaths?.length) return [];
	const collections = [];
	rawPaths.forEach((entry, index) => {
		const trimmedPath = entry?.path?.trim();
		if (!trimmedPath) return;
		let resolved;
		try {
			resolved = resolvePath(trimmedPath, workspaceDir);
		} catch {
			return;
		}
		const pattern = entry.pattern?.trim() || "**/*.md";
		const name = ensureUniqueName(entry.name?.trim() || `custom-${index + 1}`, existing);
		collections.push({
			name,
			path: resolved,
			pattern,
			kind: "custom"
		});
	});
	return collections;
}
function resolveDefaultCollections(include, workspaceDir, existing) {
	if (!include) return [];
	return [
		{
			path: workspaceDir,
			pattern: "MEMORY.md",
			base: "memory-root"
		},
		{
			path: workspaceDir,
			pattern: "memory.md",
			base: "memory-alt"
		},
		{
			path: path.join(workspaceDir, "memory"),
			pattern: "**/*.md",
			base: "memory-dir"
		}
	].map((entry) => ({
		name: ensureUniqueName(entry.base, existing),
		path: entry.path,
		pattern: entry.pattern,
		kind: "memory"
	}));
}
function resolveMemoryCollections(params) {
	const workspaceDir = resolveAgentWorkspaceDir(params.cfg, params.agentId);
	const qmdCfg = params.cfg.memory?.qmd;
	const includeDefaultMemory = qmdCfg?.includeDefaultMemory !== false;
	const nameSet = /* @__PURE__ */ new Set();
	return [...resolveDefaultCollections(includeDefaultMemory, workspaceDir, nameSet), ...resolveCustomPaths(qmdCfg?.paths, workspaceDir, nameSet)];
}
function resolveMemoryBackendConfig(params) {
	const backend = params.cfg.memory?.backend ?? DEFAULT_BACKEND;
	const citations = params.cfg.memory?.citations ?? DEFAULT_CITATIONS;
	if (backend !== "qmd") return {
		backend: "builtin",
		citations
	};
	const workspaceDir = resolveAgentWorkspaceDir(params.cfg, params.agentId);
	const qmdCfg = params.cfg.memory?.qmd;
	const includeDefaultMemory = qmdCfg?.includeDefaultMemory !== false;
	const collections = resolveMemoryCollections(params);
	return {
		backend: "qmd",
		citations,
		qmd: {
			command: resolveQmdCommand(qmdCfg?.command?.trim() || "qmd"),
			collections,
			includeDefaultMemory,
			embeddingApiKey: resolveQmdEmbeddingApiKey(params.cfg),
			sessions: resolveSessionConfig(qmdCfg?.sessions, workspaceDir),
			update: {
				intervalMs: resolveIntervalMs(qmdCfg?.update?.interval),
				debounceMs: resolveDebounceMs(qmdCfg?.update?.debounceMs),
				onBoot: qmdCfg?.update?.onBoot !== false,
				embedIntervalMs: resolveEmbedIntervalMs(qmdCfg?.update?.embedInterval),
				embedMinIntervalMs: qmdCfg?.update?.embedMinIntervalMs ?? DEFAULT_QMD_EMBED_MIN_INTERVAL_MS,
				embedMaxIntervalMs: qmdCfg?.update?.embedMaxIntervalMs ?? DEFAULT_QMD_EMBED_MAX_INTERVAL_MS,
				embedTokenThreshold: qmdCfg?.update?.embedTokenThreshold ?? DEFAULT_QMD_EMBED_TOKEN_THRESHOLD
			},
			consolidate: resolveConsolidateConfig(qmdCfg?.consolidate),
			limits: resolveLimits(qmdCfg?.limits),
			scope: qmdCfg?.scope ?? DEFAULT_QMD_SCOPE
		}
	};
}

//#endregion
export { resolveMemoryCollections as n, resolveMemoryBackendConfig as t };