import { PARENT_AGENT_ID_LABEL } from "@kong-link/protocol/agent-labels";
import { expandUserPath, resolvePathFromBase } from "../../path-utils.js";
import { toWorktreeRequestError } from "../../worktree-errors.js";
import { scheduleAgentMetadataGeneration } from "../agent-metadata-generator.js";
import { setupFinishNotification, startCreatedAgentInitialPrompt } from "../agent-prompt.js";
import { normalizeClientMessageId, resolveClientMessageId } from "../../client-message-id.js";
import { resolveRequiredProviderModel } from "../mcp-shared.js";
import { appendTimelineItemIfAgentKnown, emitLiveTimelineItemIfAgentKnown, } from "../timeline-append.js";
export async function createAgentCommand(dependencies, input) {
    const resolved = input.kind === "session"
        ? await resolveSessionCreateAgent(dependencies, input)
        : await resolveMcpCreateAgent(dependencies, input);
    const snapshot = await dependencies.agentManager.createAgent(resolved.config, undefined, resolved.createOptions);
    resolved.setupContinuation?.startAfterAgentCreate({
        agentId: snapshot.id,
    });
    let liveSnapshot = snapshot;
    let initialPromptStarted = false;
    if (resolved.prompt !== undefined) {
        const sendResult = await sendInitialPrompt(dependencies, resolved, snapshot);
        initialPromptStarted = sendResult.started;
        liveSnapshot = sendResult.liveSnapshot;
    }
    if (input.kind === "mcp" && input.notifyOnFinish && input.callerAgentId && initialPromptStarted) {
        setupFinishNotification({
            agentManager: dependencies.agentManager,
            agentStorage: dependencies.agentStorage,
            childAgentId: snapshot.id,
            callerAgentId: input.callerAgentId,
            logger: dependencies.logger,
        });
    }
    return {
        snapshot,
        liveSnapshot,
        background: resolved.background,
        initialPromptStarted,
    };
}
async function resolveSessionCreateAgent(dependencies, input) {
    const trimmedPrompt = input.initialPrompt?.trim();
    const { sessionConfig, setupContinuation } = await input.buildSessionConfig(input.config, input.git, input.worktreeName, input.firstAgentContext);
    const workspace = await input.resolveWorkspace({
        cwd: sessionConfig.cwd,
        workspaceId: input.workspaceId,
    });
    const prompt = buildAgentPrompt(trimmedPrompt ?? "", input.images, input.attachments);
    const hasPromptContent = Array.isArray(prompt) ? prompt.length > 0 : prompt.length > 0;
    const clientMessageId = normalizeClientMessageId(input.clientMessageId);
    const runOptions = input.outputSchema || clientMessageId
        ? {
            ...(input.outputSchema ? { outputSchema: input.outputSchema } : {}),
            ...(clientMessageId ? { messageId: clientMessageId } : {}),
        }
        : undefined;
    return {
        config: sessionConfig,
        createOptions: {
            labels: input.labels,
            workspaceId: workspace.workspaceId,
            initialPrompt: trimmedPrompt,
            env: input.env,
            initialTitle: input.provisionalTitle,
        },
        metadataInitialPrompt: trimmedPrompt,
        prompt: hasPromptContent ? prompt : undefined,
        runOptions,
        explicitTitle: input.explicitTitle,
        setupContinuation,
        background: true,
        promptFailure: "throw",
        promptLogger: dependencies.logger.child({
            clientMessageId: resolveClientMessageId(input.clientMessageId),
        }),
    };
}
async function resolveMcpCreateAgent(dependencies, input) {
    const resolvedProviderModel = resolveRequiredProviderModel(input.provider);
    const provider = resolvedProviderModel.provider;
    const parentAgent = input.callerAgentId
        ? requireParentAgent(dependencies.agentManager, input.callerAgentId)
        : null;
    const cwd = parentAgent
        ? resolveChildAgentCwd({
            parentCwd: parentAgent.cwd,
            requestedCwd: input.cwd,
            lockedCwd: input.callerContext?.lockedCwd,
            allowCustomCwd: input.callerContext?.allowCustomCwd ?? true,
        })
        : expandUserPath(input.cwd ?? process.cwd());
    const { resolvedCwd, setupContinuation } = await resolveMcpCwd({
        dependencies,
        cwd,
        worktree: input.worktree,
        initialPrompt: input.initialPrompt,
    });
    const { modeId: resolvedMode, featureValues: resolvedFeatures } = await dependencies.providerSnapshotManager.resolveCreateConfig({
        cwd: resolvedCwd,
        provider,
        requestedMode: input.mode,
        featureValues: input.features,
        parent: parentAgent,
        unattended: false,
    });
    const labels = mergeLabels({
        callerAgentId: input.callerAgentId,
        detached: input.detached ?? false,
        childAgentDefaultLabels: input.callerContext?.childAgentDefaultLabels,
        labels: input.labels,
    });
    const trimmedPrompt = input.initialPrompt.trim();
    return {
        config: {
            provider,
            cwd: resolvedCwd,
            modeId: resolvedMode,
            title: input.title.trim(),
            model: resolvedProviderModel.model,
            thinkingOptionId: input.thinking,
            ...(resolvedFeatures ? { featureValues: resolvedFeatures } : {}),
        },
        createOptions: labels ? { labels } : undefined,
        metadataInitialPrompt: trimmedPrompt,
        prompt: trimmedPrompt,
        explicitTitle: input.title.trim(),
        setupContinuation,
        background: input.background,
        promptFailure: "log",
    };
}
async function sendInitialPrompt(dependencies, resolved, snapshot) {
    scheduleAgentMetadataGeneration({
        agentManager: dependencies.agentManager,
        agentId: snapshot.id,
        cwd: snapshot.cwd,
        workspaceGitService: dependencies.workspaceGitService,
        providerSnapshotManager: dependencies.providerSnapshotManager,
        daemonConfig: dependencies.daemonConfig,
        currentSelection: {
            provider: snapshot.provider,
            model: snapshot.runtimeInfo?.model ?? resolved.config.model,
            thinkingOptionId: snapshot.runtimeInfo?.thinkingOptionId ?? resolved.config.thinkingOptionId ?? null,
        },
        initialPrompt: resolved.metadataInitialPrompt,
        explicitTitle: resolved.explicitTitle,
        paseoHome: dependencies.paseoHome,
        logger: dependencies.logger,
    });
    try {
        const prompt = resolved.prompt;
        if (prompt === undefined) {
            return { started: false, liveSnapshot: snapshot };
        }
        const liveSnapshot = await startCreatedAgentInitialPrompt({
            agentManager: dependencies.agentManager,
            agentId: snapshot.id,
            snapshot,
            prompt,
            runOptions: resolved.runOptions,
            logger: resolved.promptLogger ?? dependencies.logger,
        });
        return { started: true, liveSnapshot };
    }
    catch (error) {
        if (resolved.promptFailure === "throw") {
            throw error;
        }
        dependencies.logger.error({ err: error, agentId: snapshot.id }, "Failed to run initial prompt");
        return { started: false, liveSnapshot: snapshot };
    }
}
function buildAgentPrompt(text, images, attachments) {
    const normalized = text.trim();
    const hasImages = (images?.length ?? 0) > 0;
    const hasAttachments = (attachments?.length ?? 0) > 0;
    if (!hasImages && !hasAttachments) {
        return normalized;
    }
    const blocks = [];
    if (normalized.length > 0) {
        blocks.push({ type: "text", text: normalized });
    }
    for (const image of images ?? []) {
        blocks.push({ type: "image", data: image.data, mimeType: image.mimeType });
    }
    for (const attachment of attachments ?? []) {
        blocks.push(attachment);
    }
    return blocks;
}
function requireParentAgent(agentManager, parentAgentId) {
    const parentAgent = agentManager.getAgent(parentAgentId);
    if (!parentAgent) {
        throw new Error(`Parent agent ${parentAgentId} not found`);
    }
    return parentAgent;
}
function resolveChildAgentCwd(params) {
    const lockedCwd = params.lockedCwd?.trim();
    if (lockedCwd) {
        return expandUserPath(lockedCwd);
    }
    const requestedCwd = params.requestedCwd?.trim();
    if (!requestedCwd || !params.allowCustomCwd) {
        return params.parentCwd;
    }
    return resolvePathFromBase(params.parentCwd, requestedCwd);
}
async function resolveMcpCwd(params) {
    const { dependencies, worktree } = params;
    if (!worktree) {
        return { resolvedCwd: params.cwd };
    }
    const shouldCreateWorktree = Boolean(worktree.worktreeName || worktree.refName || worktree.action || worktree.githubPrNumber);
    if (!shouldCreateWorktree) {
        return { resolvedCwd: params.cwd };
    }
    if (worktree.worktreeName &&
        !worktree.baseBranch &&
        !worktree.refName &&
        !worktree.action &&
        worktree.githubPrNumber === undefined) {
        throw new Error("baseBranch is required when creating a worktree");
    }
    const baseBranch = worktree.baseBranch;
    const createdWorktree = await createMcpWorktree({
        input: {
            cwd: params.cwd,
            worktreeSlug: worktree.worktreeName,
            refName: worktree.refName,
            action: worktree.action,
            githubPrNumber: worktree.githubPrNumber,
            ...(params.initialPrompt ? { firstAgentContext: { prompt: params.initialPrompt } } : {}),
            runSetup: false,
            paseoHome: dependencies.paseoHome,
            worktreesRoot: dependencies.worktreesRoot,
        },
        createPaseoWorktree: dependencies.createPaseoWorktree,
        resolveDefaultBranch: baseBranch ? async () => baseBranch : undefined,
        setupContinuation: {
            kind: "agent",
            terminalManager: dependencies.terminalManager ?? null,
            appendTimelineItem: ({ agentId, item }) => appendTimelineItemIfAgentKnown({
                agentManager: dependencies.agentManager,
                agentId,
                item,
            }),
            emitLiveTimelineItem: ({ agentId, item }) => emitLiveTimelineItemIfAgentKnown({
                agentManager: dependencies.agentManager,
                agentId,
                item,
            }),
            logger: dependencies.logger,
        },
    });
    return {
        resolvedCwd: createdWorktree.worktree.worktreePath,
        setupContinuation: createdWorktree.setupContinuation,
    };
}
async function createMcpWorktree(options) {
    try {
        if (!options.createPaseoWorktree) {
            throw new Error("Paseo worktree service is not configured");
        }
        return await options.createPaseoWorktree(options.input, {
            ...(options.resolveDefaultBranch
                ? { resolveDefaultBranch: options.resolveDefaultBranch }
                : {}),
            ...(options.setupContinuation ? { setupContinuation: options.setupContinuation } : {}),
        });
    }
    catch (error) {
        throw toWorktreeRequestError(error);
    }
}
function mergeLabels(params) {
    const mergedLabels = {
        ...(!params.detached && params.callerAgentId
            ? { [PARENT_AGENT_ID_LABEL]: params.callerAgentId }
            : {}),
        ...params.childAgentDefaultLabels,
        ...params.labels,
    };
    if (params.detached) {
        delete mergedLabels[PARENT_AGENT_ID_LABEL];
    }
    return Object.keys(mergedLabels).length > 0 ? mergedLabels : undefined;
}
//# sourceMappingURL=create.js.map