//#endregion
//#region src/lib/chat/tool-strip.ts
function valueToText(value) {
	if (typeof value === "string") return value;
	if (value == null) return "";
	if (typeof value === "number" || typeof value === "boolean") return String(value);
	try {
		return JSON.stringify(value);
	} catch {
		return "";
	}
}
function firstText(...values) {
	for (const value of values) {
		const text = valueToText(value);
		if (text) return text;
	}
	return "";
}
function toolStripEntryFromSessionPart(part, fallbackId) {
	if (part.type !== "tool" && !part.state) return null;
	const status = part.state?.status ?? "running";
	return {
		id: part.callID ?? part.id ?? fallbackId,
		kind: "tool",
		tool: part.tool ?? "tool",
		status,
		title: part.state?.title ?? part.tool ?? "tool",
		detail: firstText(part.state?.input, part.state?.metadata, part.state?.progress, part.state?.output),
		output: valueToText(part.state?.output),
		error: part.state?.error ?? "",
		updatedAt: Date.now()
	};
}
//#endregion
//#region src/lib/api.ts
var apiBase = "";
function buildHeaders() {
	return {
		"x-request-id": crypto.randomUUID(),
		"x-requested-by": "ui"
	};
}
async function request(method, path, body) {
	const headers = {
		...body !== void 0 ? { "content-type": "application/json" } : {},
		...buildHeaders()
	};
	return fetch(`${apiBase}${path}`, {
		method,
		headers,
		credentials: "include",
		...body !== void 0 ? { body: JSON.stringify(body) } : {}
	});
}
async function readErrorMessage(res, fallback = `Request failed (HTTP ${res.status})`) {
	if ((res.headers.get("content-type") ?? "").includes("application/json")) {
		const data = await res.clone().json().catch((e) => {
			console.warn("[api] Failed to parse JSON error response:", e);
			return null;
		});
		if (data && typeof data.message === "string" && data.message.length > 0) return data.message;
		if (data && typeof data.error === "string" && data.error.length > 0) return data.error;
	}
	return await res.text().catch((e) => {
		console.warn("[api] Failed to read error response text:", e);
		return "";
	}) || fallback;
}
/** Throw on 401; throw readErrorMessage on non-OK. Returns the response. */
async function requireOk(res, fallback) {
	if (res.status === 401) throw Object.assign(/* @__PURE__ */ new Error("Sign-in required."), { status: 401 });
	if (!res.ok) throw new Error(await readErrorMessage(res, fallback));
	return res;
}
async function fetchContainers() {
	return await (await requireOk(await request("GET", "/admin/containers/list"))).json();
}
async function upgradeStack() {
	return await (await requireOk(await request("POST", "/admin/upgrade", {}))).json();
}
async function fetchVersions(opts = {}) {
	return await (await requireOk(await request("GET", `/admin/versions${opts.refresh ? "?refresh=1" : ""}`))).json();
}
async function fetchReleases(opts = {}) {
	try {
		const res = await request("GET", `/admin/versions/releases${opts.refresh ? "?refresh=1" : ""}`);
		if (!res.ok) return { releases: [] };
		return await res.json();
	} catch {
		return { releases: [] };
	}
}
/**
* List installable @openpalm/ui npm versions for the admin "UI build" picker.
* The UI is independently versioned and distributed via npm, so these — not
* GitHub platform release tags — are the valid inputs to downloadUiVersion().
*/
async function fetchUiVersions(opts = {}) {
	try {
		const res = await request("GET", `/admin/versions/ui${opts.refresh ? "?refresh=1" : ""}`);
		if (!res.ok) return { versions: [] };
		return await res.json();
	} catch {
		return { versions: [] };
	}
}
/** Invalidate all server-side version caches. Called by the "Check for updates"
*  button before re-fetching versions + releases + UI versions. The subsequent
*  GETs see a cold cache and hit the upstreams once, then cache for the TTL. */
async function invalidateVersionCache() {
	try {
		await requireOk(await request("POST", "/admin/versions/refresh"));
	} catch {}
}
/** Thrown by setStackVersion / setUnitImageTag when the target is a downgrade
*  and confirmation is required (#501). The caller shows a plain warning +
*  confirm, then re-calls with `confirmDowngrade: true`. */
var DowngradeConfirmationRequiredError = class extends Error {
	code = "downgrade_confirmation_required";
	currentVersion;
	targetVersion;
	constructor(message, currentVersion, targetVersion) {
		super(message);
		this.name = "DowngradeConfirmationRequiredError";
		this.currentVersion = currentVersion;
		this.targetVersion = targetVersion;
	}
};
/** Parse a 409 downgrade-confirmation response into the typed signal, or null
*  when the response is not a downgrade confirmation. Shared by the stack-wide
*  and per-unit tag setters so the 409 contract is handled in one place. */
async function parseDowngradeConfirmation(res, tag) {
	if (res.status !== 409) return null;
	let body = {};
	try {
		body = await res.clone().json();
	} catch {}
	if (body.error === "downgrade_confirmation_required") return new DowngradeConfirmationRequiredError(body.message ?? "This is a downgrade and requires confirmation.", body.details?.currentVersion ?? "", body.details?.targetVersion ?? tag);
	return null;
}
/** Pin a SINGLE deployable unit's image tag (assistant/guardian/portals/voice).
*  Writes only that unit's OP_*_IMAGE_TAG — the rest of the stack is untouched. */
async function setUnitImageTag(unit, tag, opts = {}) {
	const res = await request("PATCH", "/admin/stack-version", {
		unit,
		tag,
		...opts.confirmDowngrade ? { confirmDowngrade: true } : {}
	});
	const downgrade = await parseDowngradeConfirmation(res, tag);
	if (downgrade) throw downgrade;
	await requireOk(res);
	return await res.json();
}
async function downloadUiVersion(tag) {
	return await (await requireOk(await request("POST", "/admin/ui-version", { tag }))).json();
}
async function fetchAutomations() {
	return await (await requireOk(await request("GET", "/admin/automations"))).json();
}
async function fetchServiceLogs(options) {
	const params = new URLSearchParams();
	params.set("tail", String(options.tail));
	if (options?.since) params.set("since", options.since);
	const qs = params.toString();
	return await (await requireOk(await request("GET", `/admin/logs${qs ? `?${qs}` : ""}`))).json();
}
async function detectAkmEmbedding() {
	return await (await requireOk(await request("POST", "/admin/akm/embedding/detect", {}))).json();
}
async function testAkmEmbedding(settings) {
	return await (await requireOk(await request("POST", "/admin/akm/embedding/test", settings))).json();
}
async function fetchEndpoints() {
	return await (await requireOk(await request("GET", "/admin/endpoints"))).json();
}
async function setActiveEndpoint(id) {
	return await (await requireOk(await request("POST", "/admin/endpoints/active", { id }))).json();
}
/**
* Create a new OpenCode session via the SvelteKit broker.
*
* Only `/proxy/assistant/*` is reachable from the browser. The active
* OpenCode instance is selected server-side via the connection switcher.
*/
async function createSession() {
	return await (await requireOk(await request("POST", `/proxy/assistant/session`, {}))).json();
}
/**
* List sessions on the active OpenCode endpoint.
*
* OpenCode returns `Array<Session>` with no ordering guarantee; we sort
* desc by `time.updated` here so consumers can rely on it. See
* docs/technical/multi-endpoint-session-ux.md §2.
*/
async function listSessions() {
	const summaries = (await (await requireOk(await request("GET", "/proxy/assistant/session"))).json()).map((s) => ({
		id: s.id,
		title: s.title ?? "",
		createdAt: s.time?.created ?? 0,
		updatedAt: s.time?.updated ?? s.time?.created ?? 0
	}));
	summaries.sort((a, b) => b.updatedAt - a.updatedAt);
	return summaries;
}
/**
* Fetch the messages for a session and map them to UI `ChatEntry`s.
*
* Tool parts are grouped into the assistant turn that follows them (attached
* as `toolStates` on the `ChatMessage`). If tool parts appear with no
* following assistant text in the same OpenCode message they are emitted as a
* single `ChatToolGroup` entry — never as N separate entries.
*
* Skips non-text, non-tool parts (files, reasoning, etc.). Empty-text
* messages with no tool activity are dropped.
*/
async function getSessionMessages(sessionId) {
	const rows = await (await requireOk(await request("GET", `/proxy/assistant/session/${encodeURIComponent(sessionId)}/message`))).json();
	const messages = [];
	for (const row of rows) {
		const timestamp = row.info.time?.created ?? Date.now();
		let textBuffer = "";
		let textIndex = 0;
		const pendingToolStates = [];
		const flushText = () => {
			const text = textBuffer.trim();
			textBuffer = "";
			if (!text && pendingToolStates.length === 0) return;
			if (text) {
				const entry = {
					id: textIndex === 0 ? row.info.id : `${row.info.id}:text:${textIndex}`,
					role: row.info.role,
					text,
					timestamp
				};
				if (pendingToolStates.length > 0) {
					entry.toolStates = [...pendingToolStates];
					pendingToolStates.length = 0;
				}
				messages.push(entry);
				textIndex += 1;
			} else if (pendingToolStates.length > 0) {
				const group = {
					id: `${row.info.id}:tools:${textIndex}`,
					type: "tool-group",
					toolStates: [...pendingToolStates],
					timestamp
				};
				pendingToolStates.length = 0;
				messages.push(group);
				textIndex += 1;
			}
		};
		row.parts.forEach((part, index) => {
			if (part.type === "text" && part.text) {
				textBuffer += part.text;
				return;
			}
			if (part.type === "tool" || part.state) {
				const toolState = toolStripEntryFromSessionPart(part, `${row.info.id}:${index}`);
				if (!toolState) return;
				pendingToolStates.push(toolState);
			}
		});
		flushText();
	}
	return messages;
}
/**
* Send a message to an existing OpenCode session via the SvelteKit broker.
* Uses direct fetch with a 150s AbortSignal timeout — OpenCode responses
* can take 30–120s.
*/
async function sendChatMessage(sessionId, text) {
	const res = await fetch(`/proxy/assistant/session/${encodeURIComponent(sessionId)}/message`, {
		method: "POST",
		headers: {
			"content-type": "application/json",
			...buildHeaders()
		},
		credentials: "include",
		body: JSON.stringify({ parts: [{
			type: "text",
			text
		}] }),
		signal: AbortSignal.timeout(15e4)
	});
	if (res.status === 401) throw Object.assign(/* @__PURE__ */ new Error("Sign-in required."), { status: 401 });
	if (!res.ok) {
		const msg = await readErrorMessage(res);
		throw Object.assign(new Error(msg), { status: res.status });
	}
	return await res.json();
}
async function startChatMessageTurn(sessionId, text) {
	const res = await fetch(`/proxy/assistant/session/${encodeURIComponent(sessionId)}/message`, {
		method: "POST",
		headers: {
			"content-type": "application/json",
			...buildHeaders()
		},
		credentials: "include",
		body: JSON.stringify({ parts: [{
			type: "text",
			text
		}] }),
		signal: AbortSignal.timeout(15e4)
	});
	if (res.status === 401) throw Object.assign(/* @__PURE__ */ new Error("Sign-in required."), { status: 401 });
	if (!res.ok) {
		const msg = await readErrorMessage(res);
		throw Object.assign(new Error(msg), { status: res.status });
	}
}
async function replyChatPermission(requestId, reply) {
	await (await requireOk(await request("POST", `/proxy/assistant/permission/${encodeURIComponent(requestId)}/reply`, { reply }))).text().catch(() => "");
}
async function replyChatQuestion(requestId, answers) {
	await (await requireOk(await request("POST", `/proxy/assistant/question/${encodeURIComponent(requestId)}/reply`, { answers }))).text().catch(() => "");
}
async function rejectChatQuestion(requestId) {
	await (await requireOk(await request("POST", `/proxy/assistant/question/${encodeURIComponent(requestId)}/reject`, {}))).text().catch(() => "");
}
//#endregion
//#region src/lib/notifications.svelte.ts
var DEFAULT_TIMEOUTS = {
	info: 4e3,
	success: 5e3,
	error: 8e3
};
var Notifications = class {
	toasts = [];
	timers = /* @__PURE__ */ new Map();
	push(kind, message, opts = {}) {
		const id = opts.replaceId ?? (typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `t-${Date.now()}-${Math.random().toString(36).slice(2)}`);
		const ttlMs = opts.sticky ? null : opts.ttlMs ?? DEFAULT_TIMEOUTS[kind];
		const toast = {
			id,
			kind,
			message,
			ttlMs
		};
		const existingTimer = this.timers.get(id);
		if (existingTimer) {
			clearTimeout(existingTimer);
			this.timers.delete(id);
		}
		const existingIdx = this.toasts.findIndex((t) => t.id === id);
		if (existingIdx >= 0) {
			const next = [...this.toasts];
			next[existingIdx] = toast;
			this.toasts = next;
		} else this.toasts = [...this.toasts, toast];
		if (ttlMs !== null) {
			const timer = setTimeout(() => this.dismiss(id), ttlMs);
			this.timers.set(id, timer);
		}
		return id;
	}
	dismiss(id) {
		const timer = this.timers.get(id);
		if (timer) {
			clearTimeout(timer);
			this.timers.delete(id);
		}
		this.toasts = this.toasts.filter((t) => t.id !== id);
	}
	clear() {
		for (const timer of this.timers.values()) clearTimeout(timer);
		this.timers.clear();
		this.toasts = [];
	}
};
var notifications = new Notifications();
var VoiceState = class {
	status = "idle";
	/** True when the configured STT engine is actually usable from this browser. */
	sttSupported = false;
	ttsSupported = false;
	errorMessage = "";
	/** Partial transcript text while browser STT is mid-utterance. Cleared on stop/error. */
	interimTranscript = "";
	/** Active engine resolved from /admin/voice. */
	sttEngine = "disabled";
	ttsEngine = "disabled";
	/** Optional language hint (forwarded to /api/transcribe). */
	sttLanguage = "";
	/** Global toggle: when true, assistant chat replies are spoken automatically. */
	ttsAutoEnabled = false;
	/**
	* True when an audio.play() was rejected by the browser's autoplay
	* policy and we have a pending utterance waiting for a user gesture.
	* The chat UI renders a small "click to resume" banner; clicking it
	* calls resumeAutoplay() to actually play.
	*/
	autoplayBlocked = false;
	/**
	* Set when the configured STT engine is technically present in the
	* window but known to fail at runtime on this UA (e.g. iOS Safari
	* exposes SpeechRecognition but `start()` immediately errors with
	* `service-not-allowed`). The Voice settings tab uses this to hide or
	* disable the Browser STT card with the reason as a tooltip.
	*/
	browserSttUnsupportedReason = "";
};
var voiceState = new VoiceState();
var activeAudio = null;
var activeAudioUrl = null;
var SPEAK_QUEUE_MAX = 3;
var speakQueue = [];
var overflowNoticed = false;
var pendingAutoplayAudio = null;
var pendingAutoplayUrl = null;
function teardownActiveAudio() {
	if (activeAudio) {
		activeAudio.onerror = null;
		activeAudio.onended = null;
		try {
			activeAudio.pause();
		} catch {}
		activeAudio.src = "";
		activeAudio = null;
	}
	if (activeAudioUrl) {
		URL.revokeObjectURL(activeAudioUrl);
		activeAudioUrl = null;
	}
}
function teardownPendingAutoplay() {
	if (pendingAutoplayAudio) {
		pendingAutoplayAudio.onerror = null;
		pendingAutoplayAudio.onended = null;
		try {
			pendingAutoplayAudio.pause();
		} catch {}
		pendingAutoplayAudio.src = "";
		pendingAutoplayAudio = null;
	}
	if (pendingAutoplayUrl) {
		URL.revokeObjectURL(pendingAutoplayUrl);
		pendingAutoplayUrl = null;
	}
	voiceState.autoplayBlocked = false;
}
/**
* Read text aloud. Tries server-side TTS via /api/speak first (when the
* configured engine is openpalm-voice or remote); falls back to browser
* speech synthesis. Silent no-op if neither path is available.
*
* If a previous utterance is still playing, queues this one (FIFO, cap 3)
* instead of cutting it off mid-sentence.
*/
async function speakText(text, options) {
	if (typeof window === "undefined" || !text.trim()) return;
	if (voiceState.status === "speaking") {
		speakQueue.push({
			text,
			options
		});
		let dropped = 0;
		while (speakQueue.length > SPEAK_QUEUE_MAX) {
			speakQueue.shift();
			dropped += 1;
		}
		if (dropped > 0 && !overflowNoticed) {
			overflowNoticed = true;
			notifications.push("info", `Skipped ${dropped} spoken ${dropped === 1 ? "reply" : "replies"} — too much overlap. Lower the auto-speak chat rate.`);
		}
		return;
	}
	await playOne(text, options);
}
/** Internal: actually trigger the audio for one text chunk. */
async function playOne(text, options) {
	if (typeof window === "undefined" || !text.trim()) return;
	teardownPendingAutoplay();
	teardownActiveAudio();
	if ("speechSynthesis" in window) window.speechSynthesis.cancel();
	voiceState.errorMessage = "";
	const engine = voiceState.ttsEngine;
	const useServer = engine === "openpalm-voice" || engine === "remote";
	if (useServer) {
		let res;
		try {
			res = await fetch("/api/speak", {
				method: "POST",
				headers: { "content-type": "application/json" },
				credentials: "include",
				body: JSON.stringify({
					text,
					...options?.mode && options.mode !== "plain" ? { mode: options.mode } : {},
					...options?.userText ? { userText: options.userText } : {},
					...options?.assistantText ? { assistantText: options.assistantText } : {}
				})
			});
		} catch {}
		if (res && res.ok && res.headers.get("content-type")?.startsWith("audio/")) {
			const blob = await res.blob();
			const url = URL.createObjectURL(blob);
			const audio = new Audio(url);
			activeAudio = audio;
			activeAudioUrl = url;
			audio.onended = () => {
				voiceState.status = "idle";
				teardownActiveAudio();
				const next = speakQueue.shift();
				if (next) playOne(next.text, next.options);
				else overflowNoticed = false;
			};
			audio.onerror = () => {
				voiceState.status = "idle";
				voiceState.errorMessage = "Audio playback failed.";
				teardownActiveAudio();
				const next = speakQueue.shift();
				if (next) playOne(next.text, next.options);
				else overflowNoticed = false;
			};
			voiceState.status = "speaking";
			try {
				await audio.play();
			} catch {
				voiceState.status = "idle";
				pendingAutoplayAudio = audio;
				pendingAutoplayUrl = url;
				activeAudio = null;
				activeAudioUrl = null;
				voiceState.autoplayBlocked = true;
			}
			return;
		}
		if (res && !res.ok) voiceState.errorMessage = await extractSpeakError(res);
	}
	if (!("speechSynthesis" in window)) return;
	if (useServer) voiceState.errorMessage = "";
	const utterance = new SpeechSynthesisUtterance(text);
	utterance.onstart = () => {
		voiceState.status = "speaking";
	};
	utterance.onend = () => {
		voiceState.status = "idle";
		const next = speakQueue.shift();
		if (next) playOne(next.text, next.options);
		else overflowNoticed = false;
	};
	utterance.onerror = () => {
		voiceState.status = "idle";
		const next = speakQueue.shift();
		if (next) playOne(next.text, next.options);
		else overflowNoticed = false;
	};
	window.speechSynthesis.speak(utterance);
}
/**
* Convert a non-OK /api/speak response into a human-readable string.
* Recognises the two common shapes the route returns; falls back to a
* generic message keyed off the HTTP status.
*/
async function extractSpeakError(res) {
	let code;
	try {
		const data = await res.clone().json();
		if (typeof data.error === "string") code = data.error;
	} catch {}
	if (code === "tts_not_configured") return "TTS is not configured.";
	if (code === "upstream_error" || res.status === 502 || res.status === 503) return "Voice engine is warming up — try again in a moment.";
	return `TTS failed (HTTP ${res.status}).`;
}
/** Cancel speech synthesis. Drops the entire queue. */
function stopSpeaking() {
	speakQueue.length = 0;
	overflowNoticed = false;
	teardownPendingAutoplay();
	teardownActiveAudio();
	if (typeof window !== "undefined" && "speechSynthesis" in window) window.speechSynthesis.cancel();
	voiceState.status = "idle";
}
/**
* Tear down per-component voice resources on unmount. Only cancels
* any in-flight recording / recognition.
*
* Deliberately does NOT cancel `speechSynthesis` — that queue is a
* window-level singleton and the user's auto-TTS toggle is persistent,
* so a page navigation must not interrupt the assistant mid-utterance.
* Explicit user actions (logout, mic click, toggle off) call
* `stopSpeaking` directly.
*/
function destroyVoice() {
	voiceState.interimTranscript = "";
	voiceState.status = "idle";
}
//#endregion
//#region src/lib/theme-state.svelte.ts
var THEME_STORAGE_KEY = "openpalm.theme";
var THEME_ATTR = "data-theme";
var DARK_THEME_COLOR = "#161c22";
var LIGHT_THEME_COLOR = "#f9fafb";
function isThemePreference(value) {
	return value === "light" || value === "dark" || value === "system";
}
var ThemeService = class {
	preference = "system";
	resolved = "light";
	initialized = false;
	#mediaQuery = null;
	#mediaChangeHandler = () => {
		if (this.preference !== "system") return;
		this.resolved = this.#resolvePreference("system");
		this.#applyResolvedTheme();
	};
	init() {
		if (typeof window === "undefined" || this.initialized) return;
		this.preference = this.#readStoredPreference();
		this.resolved = this.#resolvePreference(this.preference);
		this.#subscribeToSystemTheme();
		this.#applyResolvedTheme();
		this.initialized = true;
	}
	setPreference(preference) {
		this.preference = preference;
		this.resolved = this.#resolvePreference(preference);
		this.#writeStoredPreference(preference);
		this.#applyResolvedTheme();
	}
	toggle() {
		this.setPreference(this.resolved === "dark" ? "light" : "dark");
	}
	dispose() {
		if (this.#mediaQuery) if (typeof this.#mediaQuery.removeEventListener === "function") this.#mediaQuery.removeEventListener("change", this.#mediaChangeHandler);
		else this.#mediaQuery.removeListener(this.#mediaChangeHandler);
		this.#mediaQuery = null;
		this.initialized = false;
	}
	#readStoredPreference() {
		if (typeof window === "undefined") return "system";
		try {
			const stored = window.localStorage.getItem(THEME_STORAGE_KEY);
			return isThemePreference(stored) ? stored : "system";
		} catch {
			return "system";
		}
	}
	#writeStoredPreference(preference) {
		if (typeof window === "undefined") return;
		try {
			window.localStorage.setItem(THEME_STORAGE_KEY, preference);
		} catch {}
	}
	#resolvePreference(preference) {
		if (preference === "light" || preference === "dark") return preference;
		if (typeof window === "undefined" || typeof window.matchMedia !== "function") return "light";
		return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
	}
	#subscribeToSystemTheme() {
		if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
		const nextQuery = window.matchMedia("(prefers-color-scheme: dark)");
		if (this.#mediaQuery === nextQuery) return;
		if (this.#mediaQuery) if (typeof this.#mediaQuery.removeEventListener === "function") this.#mediaQuery.removeEventListener("change", this.#mediaChangeHandler);
		else this.#mediaQuery.removeListener(this.#mediaChangeHandler);
		this.#mediaQuery = nextQuery;
		if (typeof nextQuery.addEventListener === "function") nextQuery.addEventListener("change", this.#mediaChangeHandler);
		else nextQuery.addListener(this.#mediaChangeHandler);
	}
	#applyResolvedTheme() {
		if (typeof document === "undefined") return;
		const root = document.documentElement;
		root.setAttribute(THEME_ATTR, this.resolved);
		root.style.colorScheme = this.resolved;
		const themeColorMeta = document.querySelector("meta[name=\"theme-color\"]");
		if (themeColorMeta) themeColorMeta.content = this.resolved === "dark" ? DARK_THEME_COLOR : LIGHT_THEME_COLOR;
		const colorSchemeMeta = document.querySelector("meta[name=\"color-scheme\"]");
		if (colorSchemeMeta) colorSchemeMeta.content = this.resolved;
	}
};
var themeService = new ThemeService();

export { themeService as A, upgradeStack as B, voiceState as C, DowngradeConfirmationRequiredError as D, detectAkmEmbedding as a, buildHeaders as b, createSession as c, destroyVoice as d, downloadUiVersion as e, fetchAutomations as f, fetchContainers as g, fetchEndpoints as h, fetchReleases as i, fetchServiceLogs as j, fetchUiVersions as k, fetchVersions as l, getSessionMessages as m, invalidateVersionCache as n, listSessions as o, notifications as p, replyChatPermission as q, rejectChatQuestion as r, replyChatQuestion as s, sendChatMessage as t, setActiveEndpoint as u, setUnitImageTag as v, speakText as w, startChatMessageTurn as x, stopSpeaking as y, testAkmEmbedding as z };
//# sourceMappingURL=theme-state.svelte-BsNoJAjT.js.map
