/**
 * Shared agent execution helper.
 *
 * Central function used by the cron scheduler and event watcher
 * to start agent sessions without duplicating session-launch logic.
 *
 * Uses the same lazy setMessageSender pattern as agent-tools.ts to break the
 * circular dependency with claude.ts.
 */
import { getAgent, getAgentWorkspacePath } from "./agent-file-service.js";
import { compileSystemPrompt } from "./claude-compiler.js";
import { appendActivity } from "./agent-activity.js";
import { createLogger } from "../utils/logger.js";
const log = createLogger("agent-executor");
let _sendMessage = null;
/**
 * Register the sendMessage function. Called by claude.ts on module load
 * to break the circular dependency.
 */
export function setExecutorMessageSender(fn) {
    _sendMessage = fn;
}
function getSendMessage() {
    if (!_sendMessage)
        throw new Error("sendMessage not registered for executor — call setExecutorMessageSender() first");
    return _sendMessage;
}
/**
 * Execute an agent session.
 *
 * Loads agent config, compiles identity, starts a Claude Code session
 * with Callboard tools injected, and logs the activity.
 *
 * Returns the chatId of the new session, or null if it failed.
 */
export async function executeAgent(opts) {
    const { agentAlias, prompt, triggeredBy, metadata, maxTurns, provider, model, effort, requireExplicitCompletion } = opts;
    try {
        const config = getAgent(agentAlias);
        if (!config) {
            log.error(`Agent "${agentAlias}" not found for ${triggeredBy} execution`);
            return null;
        }
        if (config.enabled === false) {
            log.warn(`Agent "${agentAlias}" is disabled — skipping ${triggeredBy} execution`);
            return null;
        }
        const workspacePath = getAgentWorkspacePath(agentAlias);
        const fullSystemPrompt = compileSystemPrompt(config, workspacePath).prompt;
        const sendMessage = getSendMessage();
        // Build async generator prompt (required when MCP servers are present)
        const promptIterable = (async function* () {
            yield {
                type: "user",
                message: { role: "user", content: prompt },
            };
        })();
        const emitter = await sendMessage({
            prompt: promptIterable,
            folder: workspacePath,
            systemPrompt: fullSystemPrompt,
            agentAlias,
            maxTurns: maxTurns ?? 200,
            triggered: true,
            triggeredBy,
            defaultPermissions: {
                fileRead: "allow",
                fileWrite: "allow",
                codeExecution: "allow",
                webAccess: "allow",
            },
            ...(provider && { provider }),
            ...(model && { model }),
            ...(effort && { effort }),
            ...(requireExplicitCompletion === true && { requireExplicitCompletion: true }),
        });
        // Wait for chat_created event to get chatId
        const chatId = await new Promise((resolve, reject) => {
            const timeout = setTimeout(() => reject(new Error("Timed out waiting for session to start")), 30_000);
            emitter.on("event", (event) => {
                if (event.type === "chat_created" && event.chatId) {
                    clearTimeout(timeout);
                    resolve(event.chatId);
                }
                else if (event.type === "error") {
                    clearTimeout(timeout);
                    reject(new Error(event.content || "Session failed to start"));
                }
            });
        });
        log.info(`[${triggeredBy}] Started session ${chatId} for agent ${agentAlias}`);
        // Log activity
        const activityType = triggeredBy === "tool" ? "system" : triggeredBy;
        appendActivity(agentAlias, {
            type: activityType,
            message: `${triggeredBy} session started`,
            metadata: {
                chatId,
                triggeredBy,
                ...metadata,
            },
        });
        return { chatId };
    }
    catch (err) {
        log.error(`[${triggeredBy}] Failed to execute agent ${agentAlias}: ${err.message}`);
        appendActivity(agentAlias, {
            type: "system",
            message: `${triggeredBy} execution failed: ${err.message}`,
            metadata: { triggeredBy, error: err.message, ...metadata },
        });
        return null;
    }
}
