
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="61b3decb-d642-570f-84d6-088fcd51b7a2")}catch(e){}}();
import { createClineMcpRuntimeService, } from "./cline-mcp-runtime-service.js";
import { extractClineSessionId } from "./cline-event-adapter.js";
import { buildSessionIdPrefix, createSessionId } from "./cline-session-state.js";
import { createClineSdkSessionHost, } from "./sdk-runtime-boundary.js";
const DEFAULT_CLINE_MAX_CONSECUTIVE_MISTAKES = 6;
function toSdkUserImages(images) {
    if (!images || images.length === 0) {
        return undefined;
    }
    const userImages = images
        .map((image) => {
        const mimeType = image.mimeType.trim();
        const data = image.data.trim();
        if (!mimeType || !data) {
            return null;
        }
        return `data:${mimeType};base64,${data}`;
    })
        .filter((image) => image !== null);
    return userImages.length > 0 ? userImages : undefined;
}
// Own the SDK session host plus the taskId <-> sessionId bindings so higher layers can stay task-oriented.
export class InMemoryClineSessionRuntime {
    onTaskEvent;
    createSessionHost;
    clineMcpRuntimeService;
    sessionIdByTaskId = new Map();
    taskIdBySessionId = new Map();
    lastStartRequestByTaskId = new Map();
    mcpToolBundleByTaskId = new Map();
    sessionHostPromise = null;
    constructor(options = {}) {
        this.onTaskEvent = options.onTaskEvent ?? null;
        this.createSessionHost = options.createSessionHost ?? createClineSdkSessionHost;
        const createMcpRuntimeService = options.createMcpRuntimeService ?? createClineMcpRuntimeService;
        this.clineMcpRuntimeService = createMcpRuntimeService();
    }
    async startTaskSession(request) {
        const requestedSessionId = createSessionId(request.taskId);
        const resolvedMode = request.mode ?? "act";
        this.lastStartRequestByTaskId.set(request.taskId, {
            taskId: request.taskId,
            cwd: request.cwd,
            providerId: request.providerId,
            modelId: request.modelId,
            mode: resolvedMode,
            apiKey: request.apiKey,
            baseUrl: request.baseUrl,
            systemPrompt: request.systemPrompt,
            userInstructionWatcher: request.userInstructionWatcher,
            requestToolApproval: request.requestToolApproval,
        });
        this.bindTaskSession(request.taskId, requestedSessionId);
        let mcpToolBundle = null;
        let startWarnings = [];
        try {
            mcpToolBundle = await this.clineMcpRuntimeService.createToolBundle();
            startWarnings = mcpToolBundle.warnings;
        }
        catch (error) {
            mcpToolBundle = null;
            const message = error instanceof Error ? error.message.trim() : String(error);
            if (message.length > 0) {
                startWarnings = [`Failed to load MCP tools: ${message}`];
            }
        }
        this.replaceTaskMcpToolBundle(request.taskId, mcpToolBundle);
        const sessionHost = await this.ensureSessionHost();
        let startResult;
        try {
            startResult = await sessionHost.start({
                config: {
                    sessionId: requestedSessionId,
                    providerId: request.providerId,
                    modelId: request.modelId,
                    apiKey: request.apiKey?.trim() || undefined,
                    baseUrl: request.baseUrl?.trim() || undefined,
                    cwd: request.cwd,
                    mode: resolvedMode,
                    enableTools: true,
                    enableSpawnAgent: false,
                    enableAgentTeams: false,
                    maxConsecutiveMistakes: DEFAULT_CLINE_MAX_CONSECUTIVE_MISTAKES,
                    systemPrompt: request.systemPrompt,
                    ...(mcpToolBundle && mcpToolBundle.tools.length > 0 ? { extraTools: mcpToolBundle.tools } : {}),
                },
                prompt: request.prompt,
                initialMessages: request.initialMessages,
                interactive: true,
                userImages: toSdkUserImages(request.images),
                userInstructionWatcher: request.userInstructionWatcher,
                requestToolApproval: request.requestToolApproval,
            });
        }
        catch (error) {
            this.clearTaskSessionBinding(request.taskId, requestedSessionId);
            await this.releaseTaskMcpToolBundle(request.taskId);
            throw error;
        }
        this.bindTaskSession(request.taskId, startResult.sessionId);
        if (startResult.sessionId !== requestedSessionId) {
            this.taskIdBySessionId.delete(requestedSessionId);
        }
        return {
            ...startResult,
            ...(startWarnings.length > 0 ? { warnings: startWarnings } : {}),
        };
    }
    async restartTaskSession(input) {
        const lastStartRequest = this.lastStartRequestByTaskId.get(input.taskId);
        if (!lastStartRequest) {
            throw new Error(`No previous Cline session config is available for task ${input.taskId}.`);
        }
        return await this.startTaskSession({
            ...lastStartRequest,
            prompt: input.prompt,
            initialMessages: input.initialMessages,
            images: input.images,
            mode: input.mode ?? lastStartRequest.mode,
        });
    }
    async sendTaskSessionInput(taskId, prompt, mode, images, delivery) {
        const sessionId = this.sessionIdByTaskId.get(taskId);
        if (!sessionId) {
            throw new Error(`No active Cline session for task ${taskId}.`);
        }
        const sessionHost = await this.ensureSessionHost();
        if (mode) {
            this.updateActiveSessionMode(sessionHost, sessionId, mode);
            this.updateLastStartRequestMode(taskId, mode);
        }
        return await sessionHost.send({
            sessionId,
            prompt,
            userImages: toSdkUserImages(images),
            ...(delivery ? { delivery } : {}),
        });
    }
    async resumeTaskSession(taskId) {
        const sessionHost = await this.ensureSessionHost();
        const record = await this.findPersistedTaskSessionRecord(taskId, sessionHost);
        if (!record) {
            return null;
        }
        this.bindTaskSession(taskId, record.sessionId);
        const messages = await sessionHost.readMessages(record.sessionId);
        return {
            record,
            messages,
        };
    }
    async stopTaskSession(taskId) {
        const sessionId = this.sessionIdByTaskId.get(taskId);
        if (!sessionId) {
            await this.releaseTaskMcpToolBundle(taskId);
            return;
        }
        const sessionHost = await this.ensureSessionHost();
        await sessionHost.stop(sessionId);
        await this.releaseTaskMcpToolBundle(taskId);
    }
    async abortTaskSession(taskId) {
        const sessionId = this.sessionIdByTaskId.get(taskId);
        if (!sessionId) {
            await this.releaseTaskMcpToolBundle(taskId);
            return;
        }
        const sessionHost = await this.ensureSessionHost();
        await sessionHost.abort(sessionId);
        await this.releaseTaskMcpToolBundle(taskId);
    }
    getTaskSessionId(taskId) {
        return this.sessionIdByTaskId.get(taskId) ?? null;
    }
    async readPersistedTaskSession(taskId) {
        const sessionHost = await this.ensureSessionHost();
        const record = await this.findPersistedTaskSessionRecord(taskId, sessionHost);
        if (!record) {
            return null;
        }
        const messages = await sessionHost.readMessages(record.sessionId);
        return {
            record,
            messages,
        };
    }
    async dispose() {
        const hostPromise = this.sessionHostPromise;
        this.sessionHostPromise = null;
        if (hostPromise) {
            try {
                const host = await hostPromise;
                await host.dispose("kanban-runtime-dispose");
            }
            catch {
                // Ignore host disposal errors.
            }
        }
        this.sessionIdByTaskId.clear();
        this.taskIdBySessionId.clear();
        this.lastStartRequestByTaskId.clear();
        const mcpBundles = [...this.mcpToolBundleByTaskId.values()];
        this.mcpToolBundleByTaskId.clear();
        await Promise.all(mcpBundles.map(async (bundle) => {
            await bundle.dispose().catch(() => undefined);
        }));
    }
    replaceTaskMcpToolBundle(taskId, bundle) {
        const current = this.mcpToolBundleByTaskId.get(taskId);
        if (current) {
            void current.dispose().catch(() => undefined);
            this.mcpToolBundleByTaskId.delete(taskId);
        }
        if (bundle) {
            this.mcpToolBundleByTaskId.set(taskId, bundle);
        }
    }
    async releaseTaskMcpToolBundle(taskId) {
        const current = this.mcpToolBundleByTaskId.get(taskId);
        if (!current) {
            return;
        }
        this.mcpToolBundleByTaskId.delete(taskId);
        await current.dispose().catch(() => undefined);
    }
    bindTaskSession(taskId, sessionId) {
        const previousSessionId = this.sessionIdByTaskId.get(taskId);
        if (previousSessionId) {
            this.taskIdBySessionId.delete(previousSessionId);
        }
        this.sessionIdByTaskId.set(taskId, sessionId);
        this.taskIdBySessionId.set(sessionId, taskId);
    }
    clearTaskSessionBinding(taskId, sessionId) {
        const activeSessionId = this.sessionIdByTaskId.get(taskId);
        if (!activeSessionId) {
            return;
        }
        if (sessionId && activeSessionId !== sessionId) {
            return;
        }
        this.sessionIdByTaskId.delete(taskId);
        this.taskIdBySessionId.delete(activeSessionId);
    }
    async findPersistedTaskSessionRecord(taskId, sessionHost) {
        const activeSessionId = this.sessionIdByTaskId.get(taskId);
        if (activeSessionId) {
            const activeRecord = (await sessionHost.get(activeSessionId)) ?? null;
            if (activeRecord) {
                return activeRecord;
            }
        }
        const sessionIdPrefix = buildSessionIdPrefix(taskId);
        const records = await sessionHost.list();
        const matchingRecord = records
            .filter((record) => record.sessionId.startsWith(sessionIdPrefix))
            .sort((left, right) => {
            const leftTimestamp = Date.parse(left.updatedAt || left.startedAt);
            const rightTimestamp = Date.parse(right.updatedAt || right.startedAt);
            return rightTimestamp - leftTimestamp;
        })[0];
        return matchingRecord ?? null;
    }
    async ensureSessionHost() {
        if (!this.sessionHostPromise) {
            this.sessionHostPromise = this.createSessionHost().then((sessionHost) => {
                sessionHost.subscribe((event) => {
                    this.handleSessionEvent(event);
                });
                return sessionHost;
            });
        }
        return await this.sessionHostPromise;
    }
    updateActiveSessionMode(sessionHost, sessionId, mode) {
        const hostWithSessions = sessionHost;
        const activeSession = hostWithSessions.sessions?.get(sessionId);
        if (activeSession?.config) {
            activeSession.config.mode = mode;
        }
    }
    updateLastStartRequestMode(taskId, mode) {
        const lastStartRequest = this.lastStartRequestByTaskId.get(taskId);
        if (!lastStartRequest) {
            return;
        }
        this.lastStartRequestByTaskId.set(taskId, {
            ...lastStartRequest,
            mode,
        });
    }
    handleSessionEvent(event) {
        const sessionId = extractClineSessionId(event);
        if (!sessionId) {
            return;
        }
        const taskId = this.taskIdBySessionId.get(sessionId);
        if (!taskId) {
            return;
        }
        const eventRecord = event && typeof event === "object" ? event : null;
        const ended = eventRecord?.type === "ended";
        if (this.onTaskEvent) {
            this.onTaskEvent(taskId, event);
        }
        if (ended) {
            this.clearTaskSessionBinding(taskId, sessionId);
            void this.releaseTaskMcpToolBundle(taskId);
        }
    }
}
export function createInMemoryClineSessionRuntime(options = {}) {
    return new InMemoryClineSessionRuntime(options);
}
//# sourceMappingURL=cline-session-runtime.js.map
//# debugId=61b3decb-d642-570f-84d6-088fcd51b7a2
