import { At as isRecord, Q as theme, yt as resolveStateDir } from "./entry.js";
import { b as ensureAuthProfileStore, c as resolveApiKeyForProfile, h as listProfilesForProvider, m as dedupeProfileIds, n as resolveAuthProfileOrder } from "./auth-profiles-D11Xw15i.js";
import { t as formatCliCommand } from "./command-format-B3nkKRhC.js";
import { p as DEFAULT_ACCOUNT_ID } from "./session-key-CFxFgYxM.js";
import { i as logDebug } from "./exec-CzwIUObA.js";
import { u as normalizeProviderId } from "./model-selection-CMx1evaF.js";
import { n as normalizeSecretInput } from "./normalize-secret-input-8lcBtVEy.js";
import { i as loadConfig } from "./config-D7TcU4qN.js";
import { n as listChannelPlugins } from "./plugins-BsEhWvLn.js";
import { n as getCustomProviderApiKey } from "./model-auth-Byr7Gic_.js";
import { t as bindAbortRelay } from "./fetch-timeout-Mawkd1Br.js";
import { n as formatTimeAgo } from "./format-relative-CxLpEQOX.js";
import os from "node:os";
import path from "node:path";
import fs from "node:fs";
import fs$1 from "node:fs/promises";
import crypto from "node:crypto";

//#region src/channels/account-summary.ts
function buildChannelAccountSnapshot(params) {
	const described = params.plugin.config.describeAccount?.(params.account, params.cfg);
	return {
		enabled: params.enabled,
		configured: params.configured,
		...described,
		accountId: params.accountId
	};
}
function formatChannelAllowFrom(params) {
	if (params.plugin.config.formatAllowFrom) return params.plugin.config.formatAllowFrom({
		cfg: params.cfg,
		accountId: params.accountId,
		allowFrom: params.allowFrom
	});
	return params.allowFrom.map((entry) => String(entry).trim()).filter(Boolean);
}

//#endregion
//#region src/infra/channel-summary.ts
const DEFAULT_OPTIONS = {
	colorize: false,
	includeAllowFrom: false
};
const formatAccountLabel = (params) => {
	const base = params.accountId || DEFAULT_ACCOUNT_ID;
	if (params.name?.trim()) return `${base} (${params.name.trim()})`;
	return base;
};
const accountLine = (label, details) => `  - ${label}${details.length ? ` (${details.join(", ")})` : ""}`;
const resolveAccountEnabled = (plugin, account, cfg) => {
	if (plugin.config.isEnabled) return plugin.config.isEnabled(account, cfg);
	if (!account || typeof account !== "object") return true;
	return account.enabled !== false;
};
const resolveAccountConfigured = async (plugin, account, cfg) => {
	if (plugin.config.isConfigured) return await plugin.config.isConfigured(account, cfg);
	return true;
};
const buildAccountDetails = (params) => {
	const details = [];
	const snapshot = params.entry.snapshot;
	if (snapshot.enabled === false) details.push("disabled");
	if (snapshot.dmPolicy) details.push(`dm:${snapshot.dmPolicy}`);
	if (snapshot.tokenSource && snapshot.tokenSource !== "none") details.push(`token:${snapshot.tokenSource}`);
	if (snapshot.botTokenSource && snapshot.botTokenSource !== "none") details.push(`bot:${snapshot.botTokenSource}`);
	if (snapshot.appTokenSource && snapshot.appTokenSource !== "none") details.push(`app:${snapshot.appTokenSource}`);
	if (snapshot.baseUrl) details.push(snapshot.baseUrl);
	if (snapshot.port != null) details.push(`port:${snapshot.port}`);
	if (snapshot.cliPath) details.push(`cli:${snapshot.cliPath}`);
	if (snapshot.dbPath) details.push(`db:${snapshot.dbPath}`);
	if (params.includeAllowFrom && snapshot.allowFrom?.length) {
		const formatted = formatChannelAllowFrom({
			plugin: params.plugin,
			cfg: params.cfg,
			accountId: snapshot.accountId,
			allowFrom: snapshot.allowFrom
		}).slice(0, 2);
		if (formatted.length > 0) details.push(`allow:${formatted.join(",")}`);
	}
	return details;
};
async function buildChannelSummary(cfg, options) {
	const effective = cfg ?? loadConfig();
	const lines = [];
	const resolved = {
		...DEFAULT_OPTIONS,
		...options
	};
	const tint = (value, color) => resolved.colorize && color ? color(value) : value;
	for (const plugin of listChannelPlugins()) {
		const accountIds = plugin.config.listAccountIds(effective);
		const defaultAccountId = plugin.config.defaultAccountId?.(effective) ?? accountIds[0] ?? DEFAULT_ACCOUNT_ID;
		const resolvedAccountIds = accountIds.length > 0 ? accountIds : [defaultAccountId];
		const entries = [];
		for (const accountId of resolvedAccountIds) {
			const account = plugin.config.resolveAccount(effective, accountId);
			const enabled = resolveAccountEnabled(plugin, account, effective);
			const configured = await resolveAccountConfigured(plugin, account, effective);
			const snapshot = buildChannelAccountSnapshot({
				plugin,
				account,
				cfg: effective,
				accountId,
				enabled,
				configured
			});
			entries.push({
				accountId,
				account,
				enabled,
				configured,
				snapshot
			});
		}
		const configuredEntries = entries.filter((entry) => entry.configured);
		const anyEnabled = entries.some((entry) => entry.enabled);
		const fallbackEntry = entries.find((entry) => entry.accountId === defaultAccountId) ?? entries[0];
		const summaryRecord = plugin.status?.buildChannelSummary ? await plugin.status.buildChannelSummary({
			account: fallbackEntry?.account ?? {},
			cfg: effective,
			defaultAccountId,
			snapshot: fallbackEntry?.snapshot ?? { accountId: defaultAccountId }
		}) : void 0;
		const linked = summaryRecord && typeof summaryRecord.linked === "boolean" ? summaryRecord.linked : null;
		const configured = summaryRecord && typeof summaryRecord.configured === "boolean" ? summaryRecord.configured : configuredEntries.length > 0;
		const status = !anyEnabled ? "disabled" : linked !== null ? linked ? "linked" : "not linked" : configured ? "configured" : "not configured";
		const statusColor = status === "linked" || status === "configured" ? theme.success : status === "not linked" ? theme.error : theme.muted;
		let line = `${plugin.meta.label ?? plugin.id}: ${status}`;
		const authAgeMs = summaryRecord && typeof summaryRecord.authAgeMs === "number" ? summaryRecord.authAgeMs : null;
		const self = summaryRecord?.self;
		if (self?.e164) line += ` ${self.e164}`;
		if (authAgeMs != null && authAgeMs >= 0) line += ` auth ${formatTimeAgo(authAgeMs)}`;
		lines.push(tint(line, statusColor));
		if (configuredEntries.length > 0) for (const entry of configuredEntries) {
			const details = buildAccountDetails({
				entry,
				plugin,
				cfg: effective,
				includeAllowFrom: resolved.includeAllowFrom
			});
			lines.push(accountLine(formatAccountLabel({
				accountId: entry.accountId,
				name: entry.snapshot.name
			}), details));
		}
	}
	return lines;
}

//#endregion
//#region src/infra/system-events.ts
const MAX_EVENTS = 20;
const queues = /* @__PURE__ */ new Map();
function requireSessionKey(key) {
	const trimmed = typeof key === "string" ? key.trim() : "";
	if (!trimmed) throw new Error("system events require a sessionKey");
	return trimmed;
}
function normalizeContextKey(key) {
	if (!key) return null;
	const trimmed = key.trim();
	if (!trimmed) return null;
	return trimmed.toLowerCase();
}
function isSystemEventContextChanged(sessionKey, contextKey) {
	const key = requireSessionKey(sessionKey);
	const existing = queues.get(key);
	return normalizeContextKey(contextKey) !== (existing?.lastContextKey ?? null);
}
function enqueueSystemEvent(text, options) {
	const key = requireSessionKey(options?.sessionKey);
	const entry = queues.get(key) ?? (() => {
		const created = {
			queue: [],
			lastText: null,
			lastContextKey: null
		};
		queues.set(key, created);
		return created;
	})();
	const cleaned = text.trim();
	if (!cleaned) return;
	const normalizedContextKey = normalizeContextKey(options?.contextKey);
	entry.lastContextKey = normalizedContextKey;
	if (entry.lastText === cleaned) return;
	entry.lastText = cleaned;
	entry.queue.push({
		text: cleaned,
		ts: Date.now(),
		contextKey: normalizedContextKey
	});
	if (entry.queue.length > MAX_EVENTS) entry.queue.shift();
}
function drainSystemEventEntries(sessionKey) {
	const key = requireSessionKey(sessionKey);
	const entry = queues.get(key);
	if (!entry || entry.queue.length === 0) return [];
	const out = entry.queue.slice();
	entry.queue.length = 0;
	entry.lastText = null;
	entry.lastContextKey = null;
	queues.delete(key);
	return out;
}
function peekSystemEventEntries(sessionKey) {
	const key = requireSessionKey(sessionKey);
	return queues.get(key)?.queue.map((event) => ({ ...event })) ?? [];
}
function peekSystemEvents(sessionKey) {
	return peekSystemEventEntries(sessionKey).map((event) => event.text);
}

//#endregion
//#region src/infra/provider-usage.shared.ts
const DEFAULT_TIMEOUT_MS = 5e3;
const PROVIDER_LABELS = {
	anthropic: "Claude",
	"github-copilot": "Copilot",
	"google-gemini-cli": "Gemini",
	"google-antigravity": "Antigravity",
	minimax: "MiniMax",
	"openai-codex": "Codex",
	xiaomi: "Xiaomi",
	zai: "z.ai"
};
const usageProviders = [
	"anthropic",
	"github-copilot",
	"google-gemini-cli",
	"google-antigravity",
	"minimax",
	"openai-codex",
	"xiaomi",
	"zai"
];
function resolveUsageProviderId(provider) {
	if (!provider) return;
	const normalized = normalizeProviderId(provider);
	return usageProviders.includes(normalized) ? normalized : void 0;
}
const ignoredErrors = new Set([
	"No credentials",
	"No token",
	"No API key",
	"Not logged in",
	"No auth"
]);
const clampPercent = (value) => Math.max(0, Math.min(100, Number.isFinite(value) ? value : 0));
const withTimeout = async (work, ms, fallback) => {
	let timeout;
	try {
		return await Promise.race([work, new Promise((resolve) => {
			timeout = setTimeout(() => resolve(fallback), ms);
		})]);
	} finally {
		if (timeout) clearTimeout(timeout);
	}
};

//#endregion
//#region src/infra/provider-usage.format.ts
function formatResetRemaining(targetMs, now) {
	if (!targetMs) return null;
	const diffMs = targetMs - (now ?? Date.now());
	if (diffMs <= 0) return "now";
	const diffMins = Math.floor(diffMs / 6e4);
	if (diffMins < 60) return `${diffMins}m`;
	const hours = Math.floor(diffMins / 60);
	const mins = diffMins % 60;
	if (hours < 24) return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
	const days = Math.floor(hours / 24);
	if (days < 7) return `${days}d ${hours % 24}h`;
	return new Intl.DateTimeFormat("en-US", {
		month: "short",
		day: "numeric"
	}).format(new Date(targetMs));
}
function formatUsageWindowSummary(snapshot, opts) {
	if (snapshot.error) return null;
	if (snapshot.windows.length === 0) return null;
	const now = opts?.now ?? Date.now();
	const maxWindows = typeof opts?.maxWindows === "number" && opts.maxWindows > 0 ? Math.min(opts.maxWindows, snapshot.windows.length) : snapshot.windows.length;
	const includeResets = opts?.includeResets ?? false;
	return snapshot.windows.slice(0, maxWindows).map((window) => {
		const remaining = clampPercent(100 - window.usedPercent);
		const reset = includeResets ? formatResetRemaining(window.resetAt, now) : null;
		const resetSuffix = reset ? ` ⏱${reset}` : "";
		return `${window.label} ${remaining.toFixed(0)}% left${resetSuffix}`;
	}).join(" · ");
}
function formatUsageReportLines(summary, opts) {
	if (summary.providers.length === 0) return ["Usage: no provider usage available."];
	const lines = ["Usage:"];
	for (const entry of summary.providers) {
		const planSuffix = entry.plan ? ` (${entry.plan})` : "";
		if (entry.error) {
			lines.push(`  ${entry.displayName}${planSuffix}: ${entry.error}`);
			continue;
		}
		if (entry.windows.length === 0) {
			lines.push(`  ${entry.displayName}${planSuffix}: no data`);
			continue;
		}
		lines.push(`  ${entry.displayName}${planSuffix}`);
		for (const window of entry.windows) {
			const remaining = clampPercent(100 - window.usedPercent);
			const reset = formatResetRemaining(window.resetAt, opts?.now);
			const resetSuffix = reset ? ` · resets ${reset}` : "";
			lines.push(`    ${window.label}: ${remaining.toFixed(0)}% left${resetSuffix}`);
		}
	}
	return lines;
}

//#endregion
//#region src/infra/fetch.ts
const wrapFetchWithAbortSignalMarker = Symbol.for("symi.fetch.abort-signal-wrapped");
function withDuplex(init, input) {
	const hasInitBody = init?.body != null;
	const hasRequestBody = !hasInitBody && typeof Request !== "undefined" && input instanceof Request && input.body != null;
	if (!hasInitBody && !hasRequestBody) return init;
	if (init && "duplex" in init) return init;
	return init ? {
		...init,
		duplex: "half"
	} : { duplex: "half" };
}
function wrapFetchWithAbortSignal(fetchImpl) {
	if (fetchImpl[wrapFetchWithAbortSignalMarker]) return fetchImpl;
	const wrapped = ((input, init) => {
		const patchedInit = withDuplex(init, input);
		const signal = patchedInit?.signal;
		if (!signal) return fetchImpl(input, patchedInit);
		if (typeof AbortSignal !== "undefined" && signal instanceof AbortSignal) return fetchImpl(input, patchedInit);
		if (typeof AbortController === "undefined") return fetchImpl(input, patchedInit);
		if (typeof signal.addEventListener !== "function") return fetchImpl(input, patchedInit);
		const controller = new AbortController();
		const onAbort = bindAbortRelay(controller);
		let listenerAttached = false;
		if (signal.aborted) controller.abort();
		else {
			signal.addEventListener("abort", onAbort, { once: true });
			listenerAttached = true;
		}
		const cleanup = () => {
			if (!listenerAttached || typeof signal.removeEventListener !== "function") return;
			listenerAttached = false;
			try {
				signal.removeEventListener("abort", onAbort);
			} catch {}
		};
		try {
			return fetchImpl(input, {
				...patchedInit,
				signal: controller.signal
			}).finally(cleanup);
		} catch (error) {
			cleanup();
			throw error;
		}
	});
	const wrappedFetch = Object.assign(wrapped, fetchImpl);
	const fetchWithPreconnect = fetchImpl;
	wrappedFetch.preconnect = typeof fetchWithPreconnect.preconnect === "function" ? fetchWithPreconnect.preconnect.bind(fetchWithPreconnect) : () => {};
	Object.defineProperty(wrappedFetch, wrapFetchWithAbortSignalMarker, {
		value: true,
		enumerable: false,
		configurable: false,
		writable: false
	});
	return wrappedFetch;
}
function resolveFetch(fetchImpl) {
	const resolved = fetchImpl ?? globalThis.fetch;
	if (!resolved) return;
	return wrapFetchWithAbortSignal(resolved);
}

//#endregion
//#region src/infra/provider-usage.auth.ts
function parseGoogleToken(apiKey) {
	try {
		const parsed = JSON.parse(apiKey);
		if (parsed && typeof parsed.token === "string") return { token: parsed.token };
	} catch {}
	return null;
}
function resolveZaiApiKey() {
	const envDirect = normalizeSecretInput(process.env.ZAI_API_KEY) || normalizeSecretInput(process.env.Z_AI_API_KEY);
	if (envDirect) return envDirect;
	const cfg = loadConfig();
	const key = getCustomProviderApiKey(cfg, "zai") || getCustomProviderApiKey(cfg, "z-ai");
	if (key) return key;
	const store = ensureAuthProfileStore();
	const apiProfile = [...listProfilesForProvider(store, "zai"), ...listProfilesForProvider(store, "z-ai")].find((id) => store.profiles[id]?.type === "api_key");
	if (apiProfile) {
		const cred = store.profiles[apiProfile];
		if (cred?.type === "api_key" && normalizeSecretInput(cred.key)) return normalizeSecretInput(cred.key);
	}
	try {
		const authPath = path.join(os.homedir(), ".pi", "agent", "auth.json");
		if (!fs.existsSync(authPath)) return;
		const data = JSON.parse(fs.readFileSync(authPath, "utf-8"));
		return data["z-ai"]?.access || data.zai?.access;
	} catch {
		return;
	}
}
function resolveMinimaxApiKey() {
	return resolveProviderApiKeyFromConfigAndStore({
		providerId: "minimax",
		envDirect: [process.env.MINIMAX_CODE_PLAN_KEY, process.env.MINIMAX_API_KEY]
	});
}
function resolveXiaomiApiKey() {
	return resolveProviderApiKeyFromConfigAndStore({
		providerId: "xiaomi",
		envDirect: [process.env.XIAOMI_API_KEY]
	});
}
function resolveProviderApiKeyFromConfigAndStore(params) {
	const envDirect = params.envDirect.map(normalizeSecretInput).find(Boolean);
	if (envDirect) return envDirect;
	const key = getCustomProviderApiKey(loadConfig(), params.providerId);
	if (key) return key;
	const store = ensureAuthProfileStore();
	const cred = listProfilesForProvider(store, params.providerId).map((id) => store.profiles[id]).find((profile) => profile?.type === "api_key" || profile?.type === "token");
	if (!cred) return;
	if (cred.type === "api_key") return normalizeSecretInput(cred.key);
	return normalizeSecretInput(cred.token);
}
async function resolveOAuthToken(params) {
	const cfg = loadConfig();
	const store = ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false });
	const deduped = dedupeProfileIds(resolveAuthProfileOrder({
		cfg,
		store,
		provider: params.provider
	}));
	for (const profileId of deduped) {
		const cred = store.profiles[profileId];
		if (!cred || cred.type !== "oauth" && cred.type !== "token") continue;
		try {
			const resolved = await resolveApiKeyForProfile({
				cfg: void 0,
				store,
				profileId,
				agentDir: params.agentDir
			});
			if (resolved) {
				let token = resolved.apiKey;
				if (params.provider === "google-gemini-cli" || params.provider === "google-antigravity") token = parseGoogleToken(resolved.apiKey)?.token ?? resolved.apiKey;
				return {
					provider: params.provider,
					token,
					accountId: cred.type === "oauth" && "accountId" in cred ? cred.accountId : void 0
				};
			}
		} catch {}
	}
	return null;
}
function resolveOAuthProviders(agentDir) {
	const store = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false });
	const cfg = loadConfig();
	const providers = [
		"anthropic",
		"github-copilot",
		"google-gemini-cli",
		"google-antigravity",
		"openai-codex"
	];
	const isOAuthLikeCredential = (id) => {
		const cred = store.profiles[id];
		return cred?.type === "oauth" || cred?.type === "token";
	};
	return providers.filter((provider) => {
		if (listProfilesForProvider(store, provider).filter(isOAuthLikeCredential).length > 0) return true;
		const normalized = normalizeProviderId(provider);
		return Object.entries(cfg.auth?.profiles ?? {}).filter(([, profile]) => normalizeProviderId(profile.provider) === normalized).map(([id]) => id).filter(isOAuthLikeCredential).length > 0;
	});
}
async function resolveProviderAuths(params) {
	if (params.auth) return params.auth;
	const oauthProviders = resolveOAuthProviders(params.agentDir);
	const auths = [];
	for (const provider of params.providers) {
		if (provider === "zai") {
			const apiKey = resolveZaiApiKey();
			if (apiKey) auths.push({
				provider,
				token: apiKey
			});
			continue;
		}
		if (provider === "minimax") {
			const apiKey = resolveMinimaxApiKey();
			if (apiKey) auths.push({
				provider,
				token: apiKey
			});
			continue;
		}
		if (provider === "xiaomi") {
			const apiKey = resolveXiaomiApiKey();
			if (apiKey) auths.push({
				provider,
				token: apiKey
			});
			continue;
		}
		if (!oauthProviders.includes(provider)) continue;
		const auth = await resolveOAuthToken({
			provider,
			agentDir: params.agentDir
		});
		if (auth) auths.push(auth);
	}
	return auths;
}

//#endregion
//#region src/infra/provider-usage.fetch.shared.ts
async function fetchJson(url, init, timeoutMs, fetchFn) {
	const controller = new AbortController();
	const timer = setTimeout(controller.abort.bind(controller), timeoutMs);
	try {
		return await fetchFn(url, {
			...init,
			signal: controller.signal
		});
	} finally {
		clearTimeout(timer);
	}
}
function parseFiniteNumber(value) {
	if (typeof value === "number" && Number.isFinite(value)) return value;
	if (typeof value === "string") {
		const parsed = Number.parseFloat(value);
		if (Number.isFinite(parsed)) return parsed;
	}
}
function buildUsageErrorSnapshot(provider, error) {
	return {
		provider,
		displayName: PROVIDER_LABELS[provider],
		windows: [],
		error
	};
}
function buildUsageHttpErrorSnapshot(options) {
	if ((options.tokenExpiredStatuses ?? []).includes(options.status)) return buildUsageErrorSnapshot(options.provider, "Token expired");
	const suffix = options.message?.trim() ? `: ${options.message.trim()}` : "";
	return buildUsageErrorSnapshot(options.provider, `HTTP ${options.status}${suffix}`);
}

//#endregion
//#region src/infra/provider-usage.fetch.antigravity.ts
const BASE_URL = "https://cloudcode-pa.googleapis.com";
const LOAD_CODE_ASSIST_PATH = "/v1internal:loadCodeAssist";
const FETCH_AVAILABLE_MODELS_PATH = "/v1internal:fetchAvailableModels";
const METADATA = {
	ideType: "ANTIGRAVITY",
	platform: "PLATFORM_UNSPECIFIED",
	pluginType: "GEMINI"
};
function parseNumber(value) {
	return parseFiniteNumber(value);
}
function parseEpochMs(isoString) {
	if (!isoString?.trim()) return;
	try {
		const ms = Date.parse(isoString);
		if (Number.isFinite(ms)) return ms;
	} catch {}
}
async function parseErrorMessage(res) {
	try {
		const message = (await res.json())?.error?.message?.trim();
		if (message) return message;
	} catch {}
	return `HTTP ${res.status}`;
}
function extractCredits(data) {
	const available = parseNumber(data.availablePromptCredits);
	const monthly = parseNumber(data.planInfo?.monthlyPromptCredits);
	if (available === void 0 || monthly === void 0 || monthly <= 0) return;
	return {
		available,
		monthly
	};
}
function extractPlanInfo(data) {
	const tierName = data.currentTier?.name?.trim();
	if (tierName) return tierName;
	const planType = data.planType?.trim();
	if (planType) return planType;
}
function extractProjectId(data) {
	const project = data.cloudaicompanionProject;
	if (!project) return;
	if (typeof project === "string") return project.trim() ? project : void 0;
	return (typeof project.id === "string" ? project.id.trim() : void 0) || void 0;
}
function extractModelQuotas(data) {
	const result = /* @__PURE__ */ new Map();
	if (!data.models || typeof data.models !== "object") return result;
	for (const [modelId, modelInfo] of Object.entries(data.models)) {
		const quotaInfo = modelInfo.quotaInfo;
		if (!quotaInfo) continue;
		const remainingFraction = parseNumber(quotaInfo.remainingFraction);
		if (remainingFraction === void 0) continue;
		const resetTime = parseEpochMs(quotaInfo.resetTime);
		result.set(modelId, {
			remainingFraction,
			resetTime
		});
	}
	return result;
}
function buildUsageWindows(opts) {
	const windows = [];
	if (opts.credits) {
		const { available, monthly } = opts.credits;
		const usedPercent = clampPercent((monthly - available) / monthly * 100);
		windows.push({
			label: "Credits",
			usedPercent
		});
	}
	if (opts.modelQuotas && opts.modelQuotas.size > 0) {
		const modelWindows = [];
		for (const [modelId, quota] of opts.modelQuotas) {
			const lowerModelId = modelId.toLowerCase();
			if (lowerModelId.includes("chat_") || lowerModelId.includes("tab_")) continue;
			const window = {
				label: modelId,
				usedPercent: clampPercent((1 - quota.remainingFraction) * 100)
			};
			if (quota.resetTime) window.resetAt = quota.resetTime;
			modelWindows.push(window);
		}
		modelWindows.sort((a, b) => b.usedPercent - a.usedPercent);
		const topModels = modelWindows.slice(0, 10);
		logDebug(`[antigravity] Built ${topModels.length} model windows from ${opts.modelQuotas.size} total models`);
		for (const w of topModels) logDebug(`[antigravity]   ${w.label}: ${w.usedPercent.toFixed(1)}% used${w.resetAt ? ` (resets at ${new Date(w.resetAt).toISOString()})` : ""}`);
		windows.push(...topModels);
	}
	return windows;
}
async function fetchAntigravityUsage(token, timeoutMs, fetchFn) {
	const headers = {
		Authorization: `Bearer ${token}`,
		"Content-Type": "application/json",
		"User-Agent": "antigravity",
		"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1"
	};
	let credits;
	let modelQuotas;
	let planInfo;
	let lastError;
	let projectId;
	try {
		const res = await fetchJson(`${BASE_URL}${LOAD_CODE_ASSIST_PATH}`, {
			method: "POST",
			headers,
			body: JSON.stringify({ metadata: METADATA })
		}, timeoutMs, fetchFn);
		if (res.ok) {
			const data = await res.json();
			projectId = extractProjectId(data);
			credits = extractCredits(data);
			planInfo = extractPlanInfo(data);
			logDebug(`[antigravity] Credits: ${credits ? `${credits.available}/${credits.monthly}` : "none"}${planInfo ? ` (plan: ${planInfo})` : ""}`);
		} else {
			lastError = await parseErrorMessage(res);
			if (res.status === 401) return {
				provider: "google-antigravity",
				displayName: PROVIDER_LABELS["google-antigravity"],
				windows: [],
				error: "Token expired"
			};
		}
	} catch {
		lastError = "Network error";
	}
	if (!projectId) logDebug("[antigravity] Missing project id; requesting available models without project");
	try {
		const body = JSON.stringify(projectId ? { project: projectId } : {});
		const res = await fetchJson(`${BASE_URL}${FETCH_AVAILABLE_MODELS_PATH}`, {
			method: "POST",
			headers,
			body
		}, timeoutMs, fetchFn);
		if (res.ok) {
			modelQuotas = extractModelQuotas(await res.json());
			logDebug(`[antigravity] Extracted ${modelQuotas.size} model quotas from API`);
			for (const [modelId, quota] of modelQuotas) logDebug(`[antigravity]   ${modelId}: ${(quota.remainingFraction * 100).toFixed(1)}% remaining${quota.resetTime ? ` (resets ${new Date(quota.resetTime).toISOString()})` : ""}`);
		} else {
			const err = await parseErrorMessage(res);
			if (res.status === 401) lastError = "Token expired";
			else if (!lastError) lastError = err;
		}
	} catch {
		if (!lastError) lastError = "Network error";
	}
	const windows = buildUsageWindows({
		credits,
		modelQuotas
	});
	if (windows.length === 0 && lastError) {
		logDebug(`[antigravity] Returning error snapshot: ${lastError}`);
		return {
			provider: "google-antigravity",
			displayName: PROVIDER_LABELS["google-antigravity"],
			windows: [],
			error: lastError
		};
	}
	const snapshot = {
		provider: "google-antigravity",
		displayName: PROVIDER_LABELS["google-antigravity"],
		windows,
		plan: planInfo
	};
	logDebug(`[antigravity] Returning snapshot with ${windows.length} windows${planInfo ? ` (plan: ${planInfo})` : ""}`);
	logDebug(`[antigravity] Snapshot: ${JSON.stringify(snapshot, null, 2)}`);
	return snapshot;
}

//#endregion
//#region src/infra/provider-usage.fetch.claude.ts
function buildClaudeUsageWindows(data) {
	const windows = [];
	if (data.five_hour?.utilization !== void 0) windows.push({
		label: "5h",
		usedPercent: clampPercent(data.five_hour.utilization),
		resetAt: data.five_hour.resets_at ? new Date(data.five_hour.resets_at).getTime() : void 0
	});
	if (data.seven_day?.utilization !== void 0) windows.push({
		label: "Week",
		usedPercent: clampPercent(data.seven_day.utilization),
		resetAt: data.seven_day.resets_at ? new Date(data.seven_day.resets_at).getTime() : void 0
	});
	const modelWindow = data.seven_day_sonnet || data.seven_day_opus;
	if (modelWindow?.utilization !== void 0) windows.push({
		label: data.seven_day_sonnet ? "Sonnet" : "Opus",
		usedPercent: clampPercent(modelWindow.utilization)
	});
	return windows;
}
function resolveClaudeWebSessionKey() {
	const direct = process.env.CLAUDE_AI_SESSION_KEY?.trim() ?? process.env.CLAUDE_WEB_SESSION_KEY?.trim();
	if (direct?.startsWith("sk-ant-")) return direct;
	const cookieHeader = process.env.CLAUDE_WEB_COOKIE?.trim();
	if (!cookieHeader) return;
	const value = cookieHeader.replace(/^cookie:\\s*/i, "").match(/(?:^|;\\s*)sessionKey=([^;\\s]+)/i)?.[1]?.trim();
	return value?.startsWith("sk-ant-") ? value : void 0;
}
async function fetchClaudeWebUsage(sessionKey, timeoutMs, fetchFn) {
	const headers = {
		Cookie: `sessionKey=${sessionKey}`,
		Accept: "application/json"
	};
	const orgRes = await fetchJson("https://claude.ai/api/organizations", { headers }, timeoutMs, fetchFn);
	if (!orgRes.ok) return null;
	const orgId = (await orgRes.json())?.[0]?.uuid?.trim();
	if (!orgId) return null;
	const usageRes = await fetchJson(`https://claude.ai/api/organizations/${orgId}/usage`, { headers }, timeoutMs, fetchFn);
	if (!usageRes.ok) return null;
	const windows = buildClaudeUsageWindows(await usageRes.json());
	if (windows.length === 0) return null;
	return {
		provider: "anthropic",
		displayName: PROVIDER_LABELS.anthropic,
		windows
	};
}
async function fetchClaudeUsage(token, timeoutMs, fetchFn) {
	const res = await fetchJson("https://api.anthropic.com/api/oauth/usage", { headers: {
		Authorization: `Bearer ${token}`,
		"User-Agent": "symi",
		Accept: "application/json",
		"anthropic-version": "2023-06-01",
		"anthropic-beta": "oauth-2025-04-20"
	} }, timeoutMs, fetchFn);
	if (!res.ok) {
		let message;
		try {
			const raw = (await res.json())?.error?.message;
			if (typeof raw === "string" && raw.trim()) message = raw.trim();
		} catch {}
		if (res.status === 403 && message?.includes("scope requirement user:profile")) {
			const sessionKey = resolveClaudeWebSessionKey();
			if (sessionKey) {
				const web = await fetchClaudeWebUsage(sessionKey, timeoutMs, fetchFn);
				if (web) return web;
			}
		}
		return buildUsageHttpErrorSnapshot({
			provider: "anthropic",
			status: res.status,
			message
		});
	}
	const windows = buildClaudeUsageWindows(await res.json());
	return {
		provider: "anthropic",
		displayName: PROVIDER_LABELS.anthropic,
		windows
	};
}

//#endregion
//#region src/infra/provider-usage.fetch.codex.ts
async function fetchCodexUsage(token, accountId, timeoutMs, fetchFn) {
	const headers = {
		Authorization: `Bearer ${token}`,
		"User-Agent": "CodexBar",
		Accept: "application/json"
	};
	if (accountId) headers["ChatGPT-Account-Id"] = accountId;
	const res = await fetchJson("https://chatgpt.com/backend-api/wham/usage", {
		method: "GET",
		headers
	}, timeoutMs, fetchFn);
	if (!res.ok) return buildUsageHttpErrorSnapshot({
		provider: "openai-codex",
		status: res.status,
		tokenExpiredStatuses: [401, 403]
	});
	const data = await res.json();
	const windows = [];
	if (data.rate_limit?.primary_window) {
		const pw = data.rate_limit.primary_window;
		const windowHours = Math.round((pw.limit_window_seconds || 10800) / 3600);
		windows.push({
			label: `${windowHours}h`,
			usedPercent: clampPercent(pw.used_percent || 0),
			resetAt: pw.reset_at ? pw.reset_at * 1e3 : void 0
		});
	}
	if (data.rate_limit?.secondary_window) {
		const sw = data.rate_limit.secondary_window;
		const windowHours = Math.round((sw.limit_window_seconds || 86400) / 3600);
		const label = windowHours >= 24 ? "Day" : `${windowHours}h`;
		windows.push({
			label,
			usedPercent: clampPercent(sw.used_percent || 0),
			resetAt: sw.reset_at ? sw.reset_at * 1e3 : void 0
		});
	}
	let plan = data.plan_type;
	if (data.credits?.balance !== void 0 && data.credits.balance !== null) {
		const balance = typeof data.credits.balance === "number" ? data.credits.balance : parseFloat(data.credits.balance) || 0;
		plan = plan ? `${plan} ($${balance.toFixed(2)})` : `$${balance.toFixed(2)}`;
	}
	return {
		provider: "openai-codex",
		displayName: PROVIDER_LABELS["openai-codex"],
		windows,
		plan
	};
}

//#endregion
//#region src/infra/provider-usage.fetch.copilot.ts
async function fetchCopilotUsage(token, timeoutMs, fetchFn) {
	const res = await fetchJson("https://api.github.com/copilot_internal/user", { headers: {
		Authorization: `token ${token}`,
		"Editor-Version": "vscode/1.96.2",
		"User-Agent": "GitHubCopilotChat/0.26.7",
		"X-Github-Api-Version": "2025-04-01"
	} }, timeoutMs, fetchFn);
	if (!res.ok) return buildUsageHttpErrorSnapshot({
		provider: "github-copilot",
		status: res.status
	});
	const data = await res.json();
	const windows = [];
	if (data.quota_snapshots?.premium_interactions) {
		const remaining = data.quota_snapshots.premium_interactions.percent_remaining;
		windows.push({
			label: "Premium",
			usedPercent: clampPercent(100 - (remaining ?? 0))
		});
	}
	if (data.quota_snapshots?.chat) {
		const remaining = data.quota_snapshots.chat.percent_remaining;
		windows.push({
			label: "Chat",
			usedPercent: clampPercent(100 - (remaining ?? 0))
		});
	}
	return {
		provider: "github-copilot",
		displayName: PROVIDER_LABELS["github-copilot"],
		windows,
		plan: data.copilot_plan
	};
}

//#endregion
//#region src/infra/provider-usage.fetch.gemini.ts
async function fetchGeminiUsage(token, timeoutMs, fetchFn, provider) {
	const res = await fetchJson("https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuota", {
		method: "POST",
		headers: {
			Authorization: `Bearer ${token}`,
			"Content-Type": "application/json"
		},
		body: "{}"
	}, timeoutMs, fetchFn);
	if (!res.ok) return buildUsageHttpErrorSnapshot({
		provider,
		status: res.status
	});
	const data = await res.json();
	const quotas = {};
	for (const bucket of data.buckets || []) {
		const model = bucket.modelId || "unknown";
		const frac = bucket.remainingFraction ?? 1;
		if (!quotas[model] || frac < quotas[model]) quotas[model] = frac;
	}
	const windows = [];
	let proMin = 1;
	let flashMin = 1;
	let hasPro = false;
	let hasFlash = false;
	for (const [model, frac] of Object.entries(quotas)) {
		const lower = model.toLowerCase();
		if (lower.includes("pro")) {
			hasPro = true;
			if (frac < proMin) proMin = frac;
		}
		if (lower.includes("flash")) {
			hasFlash = true;
			if (frac < flashMin) flashMin = frac;
		}
	}
	if (hasPro) windows.push({
		label: "Pro",
		usedPercent: clampPercent((1 - proMin) * 100)
	});
	if (hasFlash) windows.push({
		label: "Flash",
		usedPercent: clampPercent((1 - flashMin) * 100)
	});
	return {
		provider,
		displayName: PROVIDER_LABELS[provider],
		windows
	};
}

//#endregion
//#region src/infra/provider-usage.fetch.minimax.ts
const RESET_KEYS = [
	"reset_at",
	"resetAt",
	"reset_time",
	"resetTime",
	"next_reset_at",
	"nextResetAt",
	"next_reset_time",
	"nextResetTime",
	"expires_at",
	"expiresAt",
	"expire_at",
	"expireAt",
	"end_time",
	"endTime",
	"window_end",
	"windowEnd"
];
const PERCENT_KEYS = [
	"used_percent",
	"usedPercent",
	"usage_percent",
	"usagePercent",
	"used_rate",
	"usage_rate",
	"used_ratio",
	"usage_ratio",
	"usedRatio",
	"usageRatio"
];
const USED_KEYS = [
	"used",
	"usage",
	"used_amount",
	"usedAmount",
	"used_tokens",
	"usedTokens",
	"used_quota",
	"usedQuota",
	"used_times",
	"usedTimes",
	"prompt_used",
	"promptUsed",
	"used_prompt",
	"usedPrompt",
	"prompts_used",
	"promptsUsed",
	"current_interval_usage_count",
	"currentIntervalUsageCount",
	"consumed"
];
const TOTAL_KEYS = [
	"total",
	"total_amount",
	"totalAmount",
	"total_tokens",
	"totalTokens",
	"total_quota",
	"totalQuota",
	"total_times",
	"totalTimes",
	"prompt_total",
	"promptTotal",
	"total_prompt",
	"totalPrompt",
	"prompt_limit",
	"promptLimit",
	"limit_prompt",
	"limitPrompt",
	"prompts_total",
	"promptsTotal",
	"total_prompts",
	"totalPrompts",
	"current_interval_total_count",
	"currentIntervalTotalCount",
	"limit",
	"quota",
	"quota_limit",
	"quotaLimit",
	"max"
];
const REMAINING_KEYS = [
	"remain",
	"remaining",
	"remain_amount",
	"remainingAmount",
	"remaining_amount",
	"remain_tokens",
	"remainingTokens",
	"remaining_tokens",
	"remain_quota",
	"remainingQuota",
	"remaining_quota",
	"remain_times",
	"remainingTimes",
	"remaining_times",
	"prompt_remain",
	"promptRemain",
	"remain_prompt",
	"remainPrompt",
	"prompt_remaining",
	"promptRemaining",
	"remaining_prompt",
	"remainingPrompt",
	"prompts_remaining",
	"promptsRemaining",
	"prompt_left",
	"promptLeft",
	"prompts_left",
	"promptsLeft",
	"left"
];
const PLAN_KEYS = [
	"plan",
	"plan_name",
	"planName",
	"product",
	"tier"
];
const WINDOW_HOUR_KEYS = [
	"window_hours",
	"windowHours",
	"duration_hours",
	"durationHours",
	"hours"
];
const WINDOW_MINUTE_KEYS = [
	"window_minutes",
	"windowMinutes",
	"duration_minutes",
	"durationMinutes",
	"minutes"
];
function pickNumber(record, keys) {
	for (const key of keys) {
		const parsed = parseFiniteNumber(record[key]);
		if (parsed !== void 0) return parsed;
	}
}
function pickString(record, keys) {
	for (const key of keys) {
		const value = record[key];
		if (typeof value === "string" && value.trim()) return value.trim();
	}
}
function parseEpoch(value) {
	if (typeof value === "number" && Number.isFinite(value)) {
		if (value < 0xe8d4a51000) return Math.floor(value * 1e3);
		return Math.floor(value);
	}
	if (typeof value === "string" && value.trim()) {
		const parsed = Date.parse(value);
		if (Number.isFinite(parsed)) return parsed;
	}
}
function hasAny(record, keys) {
	return keys.some((key) => key in record);
}
function scoreUsageRecord(record) {
	let score = 0;
	if (hasAny(record, PERCENT_KEYS)) score += 4;
	if (hasAny(record, TOTAL_KEYS)) score += 3;
	if (hasAny(record, USED_KEYS) || hasAny(record, REMAINING_KEYS)) score += 2;
	if (hasAny(record, RESET_KEYS)) score += 1;
	if (hasAny(record, PLAN_KEYS)) score += 1;
	return score;
}
function collectUsageCandidates(root) {
	const MAX_SCAN_DEPTH = 4;
	const MAX_SCAN_NODES = 60;
	const queue = [{
		value: root,
		depth: 0
	}];
	const seen = /* @__PURE__ */ new Set();
	const candidates = [];
	let scanned = 0;
	while (queue.length && scanned < MAX_SCAN_NODES) {
		const next = queue.shift();
		scanned += 1;
		const { value, depth } = next;
		if (isRecord(value)) {
			if (seen.has(value)) continue;
			seen.add(value);
			const score = scoreUsageRecord(value);
			if (score > 0) candidates.push({
				record: value,
				score,
				depth
			});
			if (depth < MAX_SCAN_DEPTH) {
				for (const nested of Object.values(value)) if (isRecord(nested) || Array.isArray(nested)) queue.push({
					value: nested,
					depth: depth + 1
				});
			}
			continue;
		}
		if (Array.isArray(value) && depth < MAX_SCAN_DEPTH) {
			for (const nested of value) if (isRecord(nested) || Array.isArray(nested)) queue.push({
				value: nested,
				depth: depth + 1
			});
		}
	}
	candidates.sort((a, b) => b.score - a.score || a.depth - b.depth);
	return candidates.map((candidate) => candidate.record);
}
function deriveWindowLabel(payload) {
	const hours = pickNumber(payload, WINDOW_HOUR_KEYS);
	if (hours && Number.isFinite(hours)) return `${hours}h`;
	const minutes = pickNumber(payload, WINDOW_MINUTE_KEYS);
	if (minutes && Number.isFinite(minutes)) return `${minutes}m`;
	return "5h";
}
function deriveUsedPercent(payload) {
	const total = pickNumber(payload, TOTAL_KEYS);
	let used = pickNumber(payload, USED_KEYS);
	const remaining = pickNumber(payload, REMAINING_KEYS);
	if (used === void 0 && remaining !== void 0 && total !== void 0) used = total - remaining;
	const fromCounts = total && total > 0 && used !== void 0 && Number.isFinite(used) ? clampPercent(used / total * 100) : null;
	const percentRaw = pickNumber(payload, PERCENT_KEYS);
	if (percentRaw !== void 0) {
		const normalized = clampPercent(percentRaw <= 1 ? percentRaw * 100 : percentRaw);
		if (fromCounts !== null) return fromCounts;
		return normalized;
	}
	return fromCounts;
}
async function fetchMinimaxUsage(apiKey, timeoutMs, fetchFn) {
	const res = await fetchJson("https://api.minimaxi.com/v1/api/openplatform/coding_plan/remains", {
		method: "GET",
		headers: {
			Authorization: `Bearer ${apiKey}`,
			"Content-Type": "application/json",
			"MM-API-Source": "Symi"
		}
	}, timeoutMs, fetchFn);
	if (!res.ok) return buildUsageHttpErrorSnapshot({
		provider: "minimax",
		status: res.status
	});
	const data = await res.json().catch(() => null);
	if (!isRecord(data)) return {
		provider: "minimax",
		displayName: PROVIDER_LABELS.minimax,
		windows: [],
		error: "Invalid JSON"
	};
	const baseResp = isRecord(data.base_resp) ? data.base_resp : void 0;
	if (baseResp && typeof baseResp.status_code === "number" && baseResp.status_code !== 0) return {
		provider: "minimax",
		displayName: PROVIDER_LABELS.minimax,
		windows: [],
		error: baseResp.status_msg?.trim() || "API error"
	};
	const payload = isRecord(data.data) ? data.data : data;
	const candidates = collectUsageCandidates(payload);
	let usageRecord = payload;
	let usedPercent = null;
	for (const candidate of candidates) {
		const candidatePercent = deriveUsedPercent(candidate);
		if (candidatePercent !== null) {
			usageRecord = candidate;
			usedPercent = candidatePercent;
			break;
		}
	}
	if (usedPercent === null) usedPercent = deriveUsedPercent(payload);
	if (usedPercent === null) return {
		provider: "minimax",
		displayName: PROVIDER_LABELS.minimax,
		windows: [],
		error: "Unsupported response shape"
	};
	const resetAt = parseEpoch(pickString(usageRecord, RESET_KEYS)) ?? parseEpoch(pickNumber(usageRecord, RESET_KEYS)) ?? parseEpoch(pickString(payload, RESET_KEYS)) ?? parseEpoch(pickNumber(payload, RESET_KEYS));
	const windows = [{
		label: deriveWindowLabel(usageRecord),
		usedPercent,
		resetAt
	}];
	return {
		provider: "minimax",
		displayName: PROVIDER_LABELS.minimax,
		windows,
		plan: pickString(usageRecord, PLAN_KEYS) ?? pickString(payload, PLAN_KEYS)
	};
}

//#endregion
//#region src/infra/provider-usage.fetch.zai.ts
async function fetchZaiUsage(apiKey, timeoutMs, fetchFn) {
	const res = await fetchJson("https://api.z.ai/api/monitor/usage/quota/limit", {
		method: "GET",
		headers: {
			Authorization: `Bearer ${apiKey}`,
			Accept: "application/json"
		}
	}, timeoutMs, fetchFn);
	if (!res.ok) return buildUsageHttpErrorSnapshot({
		provider: "zai",
		status: res.status
	});
	const data = await res.json();
	if (!data.success || data.code !== 200) return {
		provider: "zai",
		displayName: PROVIDER_LABELS.zai,
		windows: [],
		error: data.msg || "API error"
	};
	const windows = [];
	const limits = data.data?.limits || [];
	for (const limit of limits) {
		const percent = clampPercent(limit.percentage || 0);
		const nextReset = limit.nextResetTime ? new Date(limit.nextResetTime).getTime() : void 0;
		let windowLabel = "Limit";
		if (limit.unit === 1) windowLabel = `${limit.number}d`;
		else if (limit.unit === 3) windowLabel = `${limit.number}h`;
		else if (limit.unit === 5) windowLabel = `${limit.number}m`;
		if (limit.type === "TOKENS_LIMIT") windows.push({
			label: `Tokens (${windowLabel})`,
			usedPercent: percent,
			resetAt: nextReset
		});
		else if (limit.type === "TIME_LIMIT") windows.push({
			label: "Monthly",
			usedPercent: percent,
			resetAt: nextReset
		});
	}
	const planName = data.data?.planName || data.data?.plan || void 0;
	return {
		provider: "zai",
		displayName: PROVIDER_LABELS.zai,
		windows,
		plan: planName
	};
}

//#endregion
//#region src/infra/provider-usage.load.ts
async function loadProviderUsageSummary(opts = {}) {
	const now = opts.now ?? Date.now();
	const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
	const fetchFn = resolveFetch(opts.fetch);
	if (!fetchFn) throw new Error("fetch is not available");
	const auths = await resolveProviderAuths({
		providers: opts.providers ?? usageProviders,
		auth: opts.auth,
		agentDir: opts.agentDir
	});
	if (auths.length === 0) return {
		updatedAt: now,
		providers: []
	};
	const tasks = auths.map((auth) => withTimeout((async () => {
		switch (auth.provider) {
			case "anthropic": return await fetchClaudeUsage(auth.token, timeoutMs, fetchFn);
			case "github-copilot": return await fetchCopilotUsage(auth.token, timeoutMs, fetchFn);
			case "google-antigravity": return await fetchAntigravityUsage(auth.token, timeoutMs, fetchFn);
			case "google-gemini-cli": return await fetchGeminiUsage(auth.token, timeoutMs, fetchFn, auth.provider);
			case "openai-codex": return await fetchCodexUsage(auth.token, auth.accountId, timeoutMs, fetchFn);
			case "minimax": return await fetchMinimaxUsage(auth.token, timeoutMs, fetchFn);
			case "xiaomi": return {
				provider: "xiaomi",
				displayName: PROVIDER_LABELS.xiaomi,
				windows: []
			};
			case "zai": return await fetchZaiUsage(auth.token, timeoutMs, fetchFn);
			default: return {
				provider: auth.provider,
				displayName: PROVIDER_LABELS[auth.provider],
				windows: [],
				error: "Unsupported provider"
			};
		}
	})(), timeoutMs + 1e3, {
		provider: auth.provider,
		displayName: PROVIDER_LABELS[auth.provider],
		windows: [],
		error: "Timeout"
	}));
	return {
		updatedAt: now,
		providers: (await Promise.all(tasks)).filter((entry) => {
			if (entry.windows.length > 0) return true;
			if (!entry.error) return true;
			return !ignoredErrors.has(entry.error);
		})
	};
}

//#endregion
//#region src/infra/restart-sentinel.ts
const SENTINEL_FILENAME = "restart-sentinel.json";
function formatDoctorNonInteractiveHint(env = process.env) {
	return `Run: ${formatCliCommand("symi doctor --non-interactive", env)}`;
}
function resolveRestartSentinelPath(env = process.env) {
	return path.join(resolveStateDir(env), SENTINEL_FILENAME);
}
async function writeRestartSentinel(payload, env = process.env) {
	const filePath = resolveRestartSentinelPath(env);
	await fs$1.mkdir(path.dirname(filePath), { recursive: true });
	const data = {
		version: 1,
		payload
	};
	await fs$1.writeFile(filePath, `${JSON.stringify(data, null, 2)}\n`, "utf-8");
	return filePath;
}
async function readRestartSentinel(env = process.env) {
	const filePath = resolveRestartSentinelPath(env);
	try {
		const raw = await fs$1.readFile(filePath, "utf-8");
		let parsed;
		try {
			parsed = JSON.parse(raw);
		} catch {
			await fs$1.unlink(filePath).catch(() => {});
			return null;
		}
		if (!parsed || parsed.version !== 1 || !parsed.payload) {
			await fs$1.unlink(filePath).catch(() => {});
			return null;
		}
		return parsed;
	} catch {
		return null;
	}
}
async function consumeRestartSentinel(env = process.env) {
	const filePath = resolveRestartSentinelPath(env);
	const parsed = await readRestartSentinel(env);
	if (!parsed) return null;
	await fs$1.unlink(filePath).catch(() => {});
	return parsed;
}
function formatRestartSentinelMessage(payload) {
	const message = payload.message?.trim();
	if (message && !payload.stats) return message;
	const lines = [summarizeRestartSentinel(payload)];
	if (message) lines.push(message);
	const reason = payload.stats?.reason?.trim();
	if (reason) lines.push(`Reason: ${reason}`);
	if (payload.doctorHint?.trim()) lines.push(payload.doctorHint.trim());
	return lines.join("\n");
}
function summarizeRestartSentinel(payload) {
	return `Gateway restart ${payload.kind} ${payload.status}${payload.stats?.mode ? ` (${payload.stats.mode})` : ""}`.trim();
}
function trimLogTail(input, maxChars = 8e3) {
	if (!input) return null;
	const text = input.trimEnd();
	if (text.length <= maxChars) return text;
	return `…${text.slice(text.length - maxChars)}`;
}

//#endregion
//#region src/logging/redact-identifier.ts
function sha256HexPrefix(value, len = 12) {
	const safeLen = Number.isFinite(len) ? Math.max(1, Math.floor(len)) : 12;
	return crypto.createHash("sha256").update(value).digest("hex").slice(0, safeLen);
}
function redactIdentifier(value, opts) {
	const trimmed = value?.trim();
	if (!trimmed) return "-";
	return `sha256:${sha256HexPrefix(trimmed, opts?.len ?? 12)}`;
}

//#endregion
export { peekSystemEvents as _, formatRestartSentinelMessage as a, formatChannelAllowFrom as b, trimLogTail as c, formatUsageReportLines as d, formatUsageWindowSummary as f, isSystemEventContextChanged as g, enqueueSystemEvent as h, formatDoctorNonInteractiveHint as i, writeRestartSentinel as l, drainSystemEventEntries as m, sha256HexPrefix as n, readRestartSentinel as o, resolveUsageProviderId as p, consumeRestartSentinel as r, summarizeRestartSentinel as s, redactIdentifier as t, loadProviderUsageSummary as u, buildChannelSummary as v, buildChannelAccountSnapshot as y };