import { createLogger } from "../../utils/logger/index.js";
import { init_logger } from "../../utils/logger.js";
import "../memory/dreaming/constants.js";
import { resolveDreamingConfig } from "../memory/dreaming/config.js";
import { extractAgentUserPlainText } from "../memory/user-message-text.js";
import { formatInboundFileTextBlock, persistInboundAttachmentsToWorkspace } from "../../channels/attachments/inbound-persist.js";
import { resolveEffectiveThinkingLevel } from "../../session/thinking-resolve.js";
import { abortEmbeddedRun } from "../embedded/runs.js";
import { runEmbeddedTurnForSession } from "../embedded/run-for-session.js";
import { expandAtFileMentionsInPlainText } from "../context/expand-at-file-mentions.js";
import { resolveInboundImageContentParts } from "../image/inbound-image-handling.js";
import { runDreamingDeepPromotion } from "../memory/dreaming/deep-promotion.js";
import { appendDreamingEvent } from "../memory/dreaming/events.js";
import { runLightSweep } from "../memory/dreaming/light-sweep.js";
import { runRemPatterns } from "../memory/dreaming/rem-patterns.js";
//#region src/agent/orchestration/agent-orchestrator.ts
init_logger();
const log = createLogger("AgentOrchestrator");
var AgentOrchestrator = class {
	agentManager;
	sessionStore;
	modelManager;
	eventHandler;
	feedbackCoordinator;
	sessionConfigStore;
	sessionHydrator;
	getThinkingDefault;
	getThinkingDefaultForSession;
	workspaceRoot;
	getWorkspaceRootForSession;
	getAgentInternalStorageRootForSession;
	enqueueAutoTitle;
	getConfig;
	onEmbeddedStreamEvent;
	onEmbeddedTurnComplete;
	constructor(config) {
		this.agentManager = config.agentManager;
		this.sessionStore = config.sessionStore;
		this.modelManager = config.modelManager;
		this.eventHandler = config.eventHandler;
		this.feedbackCoordinator = config.feedbackCoordinator;
		this.sessionConfigStore = config.sessionConfigStore;
		this.sessionHydrator = config.sessionHydrator;
		this.getThinkingDefault = config.getThinkingDefault;
		this.getThinkingDefaultForSession = config.getThinkingDefaultForSession;
		this.workspaceRoot = config.workspaceRoot;
		this.getWorkspaceRootForSession = config.getWorkspaceRootForSession;
		this.getAgentInternalStorageRootForSession = config.getAgentInternalStorageRootForSession ?? ((sk) => this.getWorkspaceRootForSession?.(sk) ?? this.workspaceRoot);
		this.enqueueAutoTitle = config.enqueueAutoTitle;
		this.getConfig = config.getConfig;
		this.onEmbeddedStreamEvent = config.onEmbeddedStreamEvent;
		this.onEmbeddedTurnComplete = config.onEmbeddedTurnComplete;
	}
	/**
	* Process a message through the agent orchestration pipeline
	*/
	async process(msg, context) {
		const { sessionKey } = context;
		log.debug({ sessionKey }, "Processing message through agent orchestrator");
		await this.sessionHydrator.workspace(sessionKey);
		if (typeof msg.content === "string" && (sessionKey.startsWith("cron:") || context.channel === "cron")) {
			const content = msg.content;
			if (content.includes("__xopc_memory_dreaming_sweep__") || content.includes("__xopc_memory_dreaming_light_sweep__") || content.includes("__xopc_memory_dreaming_rem_sweep__")) {
				const workspaceDir = this.agentManager.getResolvedWorkspaceForSession(sessionKey);
				const resolved = resolveDreamingConfig(this.getConfig?.());
				const t0 = Date.now();
				if (content.includes("__xopc_memory_dreaming_light_sweep__")) {
					const result = await runLightSweep({
						workspaceDir,
						config: resolved.phases.light
					});
					await appendDreamingEvent(workspaceDir, {
						timestamp: (/* @__PURE__ */ new Date()).toISOString(),
						phase: "light",
						ok: result.ok,
						reason: result.reason,
						durationMs: Date.now() - t0,
						scannedEntries: result.scannedEntries,
						newSignals: result.newSignals,
						deduped: result.deduped
					});
				} else if (content.includes("__xopc_memory_dreaming_rem_sweep__")) {
					const result = await runRemPatterns({
						workspaceDir,
						config: resolved.phases.rem
					});
					await appendDreamingEvent(workspaceDir, {
						timestamp: (/* @__PURE__ */ new Date()).toISOString(),
						phase: "rem",
						ok: result.ok,
						reason: result.reason,
						durationMs: Date.now() - t0,
						patternsDiscovered: result.patternsDiscovered,
						entriesAnalyzed: result.entriesAnalyzed
					});
				} else {
					const result = await runDreamingDeepPromotion({
						workspaceDir,
						config: resolved.phases.deep
					});
					await appendDreamingEvent(workspaceDir, {
						timestamp: (/* @__PURE__ */ new Date()).toISOString(),
						phase: "deep",
						ok: result.ok,
						reason: result.reason,
						durationMs: Date.now() - t0,
						candidates: result.candidates,
						applied: result.applied
					});
				}
				return;
			}
		}
		try {
			await this.sessionHydrator.model(sessionKey);
			const thinkingDefault = this.getThinkingDefaultForSession?.(sessionKey) ?? this.getThinkingDefault();
			const thinkingLevel = await resolveEffectiveThinkingLevel(this.sessionConfigStore, sessionKey, null, thinkingDefault);
			this.agentManager.setThinkingLevel(sessionKey, thinkingLevel);
			const persistedAttachments = await persistInboundAttachmentsToWorkspace(this.getAgentInternalStorageRootForSession(sessionKey), sessionKey, msg.attachments);
			const userMessage = await this.buildUserMessage({
				...msg,
				attachments: persistedAttachments ?? msg.attachments
			}, sessionKey);
			const userPlainForMemory = extractAgentUserPlainText(userMessage);
			const userMessageForModel = await this.agentManager.applyMemoryPrefetchToUserMessage(userMessage, sessionKey);
			this.feedbackCoordinator.startTask();
			const turnResult = await runEmbeddedTurnForSession({
				sessionKey,
				userMessage: userMessageForModel,
				sessionStore: this.sessionStore,
				agentManager: this.agentManager,
				modelManager: this.modelManager,
				thinkingOverride: thinkingLevel,
				getConfig: this.getConfig,
				beforeTurn: () => this.agentManager.beginBackgroundReviewUserTurn(sessionKey),
				onEvent: (event) => this.onEmbeddedStreamEvent?.(sessionKey, event)
			});
			this.agentManager.afterAgentTurn(sessionKey, userPlainForMemory);
			this.agentManager.scheduleBackgroundReviewAfterUserTurn(sessionKey);
			if (turnResult.ok) {
				this.onEmbeddedTurnComplete?.(sessionKey, turnResult.lastAssistantText);
				this.enqueueAutoTitle?.(sessionKey);
			} else if (turnResult.errorMessage) log.warn({
				sessionKey,
				errorMessage: turnResult.errorMessage
			}, "Embedded inbound turn failed");
			this.feedbackCoordinator.endTask();
		} catch (error) {
			log.error({
				err: error,
				sessionKey
			}, "Error in agent orchestration");
			this.feedbackCoordinator.endTask();
			throw error;
		}
	}
	/**
	* Build an agent message from an inbound message
	*/
	async buildUserMessage(msg, sessionKey) {
		const storageRootAbs = this.getAgentInternalStorageRootForSession(sessionKey);
		let textBody = msg.content.trimStart().startsWith("/skill:") ? this.agentManager.expandSkillUserText(msg.content) : msg.content;
		if (/@file:/.test(textBody)) {
			const root = this.agentManager.getResolvedWorkspaceForSession(sessionKey);
			textBody = await expandAtFileMentionsInPlainText(textBody, root);
		}
		if (!msg.attachments || msg.attachments.length === 0) return {
			role: "user",
			content: textBody,
			timestamp: Date.now()
		};
		const modelRef = this.modelManager.getModelForSession(sessionKey);
		const cfg = this.getConfig?.();
		const messageContent = [];
		if (msg.content.trim()) messageContent.push({
			type: "text",
			text: textBody
		});
		const attachments = msg.attachments;
		let i = 0;
		while (i < attachments.length) {
			const att = attachments[i];
			if (att.type === "image" || att.type === "photo" || Boolean(att.mimeType?.startsWith("image/"))) {
				const group = [];
				while (i < attachments.length) {
					const a = attachments[i];
					if (!(a.type === "image" || a.type === "photo" || Boolean(a.mimeType?.startsWith("image/")))) break;
					if (!a.data || a.data.length === 0) {
						log.warn({
							type: a.type,
							name: a.name
						}, "Empty image data, skipping");
						i += 1;
						continue;
					}
					group.push({
						data: a.data,
						mimeType: a.mimeType || "image/jpeg"
					});
					i += 1;
				}
				if (group.length > 0) {
					const parts = await resolveInboundImageContentParts({
						modelRef,
						cfg,
						userTextForContext: msg.content.trim() ? textBody : "",
						images: group
					});
					messageContent.push(...parts);
				}
			} else {
				const fileBlock = formatInboundFileTextBlock({
					type: att.type,
					mimeType: att.mimeType,
					name: att.name,
					size: att.size,
					workspaceRelativePath: att.workspaceRelativePath
				}, storageRootAbs);
				messageContent.push({
					type: "text",
					text: fileBlock
				});
				i += 1;
			}
		}
		const hasText = messageContent.some((item) => item.type === "text");
		if (messageContent.some((item) => item.type === "image") && !hasText) messageContent.unshift({
			type: "text",
			text: "Please analyze the image(s) I sent."
		});
		if (messageContent.length === 0) {
			log.warn({ attachmentCount: msg.attachments.length }, "All attachments were skipped, falling back to text message");
			return {
				role: "user",
				content: textBody || "[Image attachment could not be processed]",
				timestamp: Date.now()
			};
		}
		return {
			role: "user",
			content: messageContent,
			timestamp: Date.now()
		};
	}
	/**
	* Get the current agent model ID
	*/
	getCurrentModel() {
		return this.modelManager.getCurrentModel();
	}
	/**
	* Check if agent is currently processing for a session
	*/
	isProcessing(sessionKey) {
		const agent = this.agentManager.getAgent(sessionKey);
		if (!agent) return false;
		return agent.state.messages.length > 0;
	}
	/**
	* Abort current agent execution for a session
	*/
	abort(sessionKey) {
		abortEmbeddedRun(sessionKey);
		this.agentManager.getAgent(sessionKey)?.abort();
	}
};
//#endregion
export { AgentOrchestrator };

//# sourceMappingURL=agent-orchestrator.js.map