import { createLogger } from "../../utils/logger/index.js";
import { init_logger } from "../../utils/logger.js";
import { loadConfig } from "../../config/loader.js";
import { getAllProviders, getModelsByProvider, init_providers } from "../../providers/index.js";
import { prependEnvelopeTimestamp } from "../../channels/envelope-timestamp.js";
import { messagesToClientHistory } from "../../session/client-history.js";
import { getWorkspacePath } from "../../config/workspace-path-helpers.js";
import { parseModelRef } from "../../agent/models/selection.js";
import { MessageBus, MessageBusShutdownError } from "../../infra/bus/queue.js";
import "../../infra/bus/index.js";
import { AgentService } from "../../agent/service.js";
import "../../agent/index.js";
import "../../config/index.js";
import { sessionMetadataToTuiItem } from "../tui-session-format.js";
//#region src/tui/backends/embedded-backend.ts
init_providers();
init_logger();
const log = createLogger("TUI:Embedded");
/**
* TUI backend that runs the agent in-process (no gateway required).
*
* Wraps `AgentService` directly and emits TuiEvents by observing the
* `MessageBus` output stream.
*/
var EmbeddedBackend = class {
	bus;
	agent = null;
	running = false;
	chatAbort = null;
	onEvent;
	onConnected;
	onDisconnected;
	constructor(opts) {
		this.opts = opts;
		this.bus = new MessageBus();
	}
	get connectionLabel() {
		return "local embedded";
	}
	start() {
		if (this.running) return;
		this.running = true;
		const config = loadConfig();
		const workspace = getWorkspacePath(config);
		const modelId = config.agents?.defaults?.model?.primary;
		this.agent = new AgentService(this.bus, {
			workspace: workspace ?? process.cwd(),
			model: modelId,
			config,
			extensionRegistry: this.opts?.extensionRegistry
		});
		this.agent.start().catch((err) => {
			const errorMessage = err instanceof Error ? err.message : String(err);
			log.error({
				err,
				errorMessage
			}, `Embedded agent failed: ${errorMessage}`);
			this.onDisconnected?.(errorMessage);
		});
		this.processOutbound();
		queueMicrotask(() => this.onConnected?.());
	}
	stop() {
		this.running = false;
		this.chatAbort?.abort();
		this.chatAbort = null;
		this.bus.shutdown();
		this.agent?.stop();
		this.agent = null;
	}
	async sendChat(opts) {
		if (!this.agent) throw new Error("Agent not started");
		const runId = crypto.randomUUID();
		this.chatAbort?.abort();
		this.chatAbort = new AbortController();
		const signal = this.chatAbort.signal;
		this.onEvent?.({
			event: "status",
			data: {
				status: "started",
				runId
			}
		});
		(async () => {
			try {
				const messageForAgent = opts.message.trimStart().startsWith("/") ? opts.message : prependEnvelopeTimestamp(opts.message);
				const stream = this.agent.turnDispatcher.processDirectStreaming(messageForAgent, opts.sessionKey, void 0, opts.thinking, { signal });
				for await (const event of stream) {
					if (signal.aborted) break;
					this.onEvent?.({
						event: event.type,
						data: event
					});
				}
				if (!signal.aborted) this.onEvent?.({
					event: "result",
					data: { ok: true }
				});
			} catch (error) {
				if (signal.aborted) return;
				const errorMessage = error instanceof Error ? error.message : String(error);
				this.onEvent?.({
					event: "error",
					data: { content: errorMessage }
				});
			}
		})();
		return { runId };
	}
	async abortChat(_opts) {
		if (this.chatAbort) {
			this.chatAbort.abort();
			this.chatAbort = null;
			return { ok: true };
		}
		return { ok: false };
	}
	async steerChat(opts) {
		if (!this.agent) return { ok: false };
		return { ok: await this.agent.turnDispatcher.steerWebchatSession(opts.sessionKey, opts.message) };
	}
	async loadHistory(opts) {
		if (!this.agent) return { messages: [] };
		try {
			const detail = await this.agent.sessionStore.get(opts.sessionKey);
			if (!detail) return { messages: [] };
			return { messages: messagesToClientHistory(detail.messages, { limit: opts.limit }) };
		} catch (error) {
			const errorMessage = error instanceof Error ? error.message : String(error);
			log.warn({
				err: error,
				errorMessage
			}, `Embedded loadHistory failed: ${errorMessage}`);
			return { messages: [] };
		}
	}
	async listSessions() {
		if (!this.agent) return [];
		try {
			return (await this.agent.sessionStore.list({
				limit: 200,
				sortBy: "updatedAt",
				sortOrder: "desc"
			})).items.map(sessionMetadataToTuiItem);
		} catch (error) {
			const errorMessage = error instanceof Error ? error.message : String(error);
			log.warn({
				err: error,
				errorMessage
			}, `Embedded listSessions failed: ${errorMessage}`);
			return [];
		}
	}
	async renameSession(sessionKey, name) {
		if (!this.agent) return { ok: false };
		try {
			await this.agent.sessionStore.updateMetadata(sessionKey, { name: name.trim() });
			return { ok: true };
		} catch (error) {
			const errorMessage = error instanceof Error ? error.message : String(error);
			log.warn({
				err: error,
				sessionKey,
				errorMessage
			}, `Embedded renameSession failed: ${errorMessage}`);
			return { ok: false };
		}
	}
	async deleteSession(sessionKey) {
		if (!this.agent) return { ok: false };
		try {
			return { ok: await this.agent.sessionStore.deleteSession(sessionKey) };
		} catch (error) {
			const errorMessage = error instanceof Error ? error.message : String(error);
			log.warn({
				err: error,
				sessionKey,
				errorMessage
			}, `Embedded deleteSession failed: ${errorMessage}`);
			return { ok: false };
		}
	}
	async getSessionInfo(sessionKey) {
		if (!this.agent) return { model: loadConfig().agents?.defaults?.model?.primary ?? void 0 };
		try {
			const cfg = await this.agent.sessionInspector.agentConfig(sessionKey);
			const parsed = parseModelRef(cfg.model);
			const usage = await this.agent.sessionInspector.contextUsage(sessionKey);
			return {
				model: parsed?.model ?? cfg.model,
				modelProvider: parsed?.provider,
				thinkingLevel: cfg.thinkingLevel,
				totalTokens: usage.estimatedTokens,
				contextWindow: usage.contextWindow,
				contextUsagePercent: usage.usagePercent
			};
		} catch (err) {
			const errorMessage = err instanceof Error ? err.message : String(err);
			log.warn({
				err,
				sessionKey,
				errorMessage
			}, `getSessionInfo failed: ${errorMessage}`);
			return { model: loadConfig().agents?.defaults?.model?.primary ?? void 0 };
		}
	}
	async listModels() {
		const choices = [];
		for (const provider of getAllProviders()) for (const model of getModelsByProvider(provider)) choices.push({
			id: model.id,
			name: model.name ?? model.id,
			provider
		});
		return choices;
	}
	async resetSession(sessionKey) {
		if (!this.agent) return;
		await this.agent.resetSession(sessionKey);
	}
	async patchSession(_sessionKey, _patch) {}
	async compactSession(sessionKey, options) {
		if (!this.agent) return {
			compacted: false,
			summary: "Agent not started"
		};
		try {
			const result = await this.agent.sessionInspector.compact(sessionKey, { force: options?.force ?? true });
			const summary = result.compacted ? `Compacted (${result.tokensBefore ?? "?"} → ${result.tokensAfter ?? "?"} tokens)` : "Nothing to compact";
			return {
				compacted: result.compacted,
				summary
			};
		} catch (err) {
			return {
				compacted: false,
				summary: err instanceof Error ? err.message : String(err)
			};
		}
	}
	processOutbound() {
		(async () => {
			while (this.running) try {
				const msg = await this.bus.consumeOutbound();
				log.debug({
					channel: msg.channel,
					chatId: msg.chat_id
				}, "Outbound message");
			} catch (error) {
				if (error instanceof MessageBusShutdownError) break;
				const errorMessage = error instanceof Error ? error.message : String(error);
				log.warn({
					err: error,
					errorMessage
				}, `Outbound processor failed: ${errorMessage}`);
				await new Promise((resolve) => setTimeout(resolve, 1e3));
			}
		})();
	}
};
//#endregion
export { EmbeddedBackend };

//# sourceMappingURL=embedded-backend.js.map