
!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]="4e409993-3fea-5c84-979b-3a831de5c01f")}catch(e){}}();
import { isHomeAgentSessionId } from "../core/home-agent-session.js";
import { resolveHomeAgentAppendSystemPrompt } from "../prompts/append-system-prompt.js";
import { captureTaskTurnCheckpoint, deleteTaskTurnCheckpointRef } from "../workspace/turn-checkpoints.js";
import { applyClineSessionEvent } from "./cline-event-adapter.js";
import { createInMemoryClineMessageRepository, createTaskEntryFromPersistedSession, } from "./cline-message-repository.js";
import { createClineRuntimeSetup } from "./cline-runtime-setup.js";
import { createInMemoryClineSessionRuntime, } from "./cline-session-runtime.js";
import { clearActiveTurnState, cloneSummary, createAssistantMessage, createDefaultSummary, createMessage, now, setOrCreateAssistantMessage, updateSummary, } from "./cline-session-state.js";
import { resolveClineSdkSystemPrompt } from "./sdk-runtime-boundary.js";
function toErrorMessage(error) {
    if (error instanceof Error) {
        const message = error.message.trim();
        if (message.length > 0) {
            return message;
        }
    }
    return "Unknown error";
}
function readAgentResultText(result) {
    if (!result || typeof result !== "object") {
        return null;
    }
    if (!("text" in result)) {
        return null;
    }
    const text = result.text;
    if (typeof text !== "string") {
        return null;
    }
    const normalized = text.trim();
    return normalized.length > 0 ? normalized : null;
}
function formatStartWarnings(warnings) {
    if (!warnings) {
        return null;
    }
    const normalized = warnings.map((warning) => warning.trim()).filter((warning) => warning.length > 0);
    if (normalized.length === 0) {
        return null;
    }
    if (normalized.length === 1) {
        return normalized[0] ?? null;
    }
    return `${normalized[0]} (+${normalized.length - 1} more MCP warning${normalized.length === 2 ? "" : "s"})`;
}
export class InMemoryClineTaskSessionService {
    pendingTurnCancelTaskIds = new Set();
    sessionRuntime;
    messageRepository;
    createRuntimeSetup;
    runtimeSetupByWorkspacePath = new Map();
    constructor(options = {}) {
        const createSessionRuntime = options.createSessionRuntime ?? createInMemoryClineSessionRuntime;
        const createMessageRepository = options.createMessageRepository ?? createInMemoryClineMessageRepository;
        this.createRuntimeSetup = options.createRuntimeSetup ?? createClineRuntimeSetup;
        this.sessionRuntime = createSessionRuntime({
            onTaskEvent: (taskId, event) => {
                this.handleTaskEvent(taskId, event);
            },
        });
        this.messageRepository = createMessageRepository();
    }
    onSummary(listener) {
        return this.messageRepository.onSummary(listener);
    }
    onMessage(listener) {
        return this.messageRepository.onMessage(listener);
    }
    emitTaskFailure(taskId, entry, context, error) {
        const errorMessage = toErrorMessage(error);
        const systemMessage = createMessage(taskId, "system", `Cline SDK ${context} failed: ${errorMessage}. You can send another message to continue the conversation.`);
        entry.messages.push(systemMessage);
        this.emitMessage(taskId, systemMessage);
        clearActiveTurnState(entry);
        const errorSummary = updateSummary(entry, {
            state: "awaiting_review",
            reviewReason: "error",
            lastOutputAt: now(),
            lastHookAt: now(),
            warningMessage: errorMessage,
            latestHookActivity: {
                activityText: `${context === "start" ? "Start" : "Send"} failed: ${errorMessage}`,
                toolName: null,
                toolInputSummary: null,
                finalMessage: errorMessage,
                hookEventName: "agent_error",
                notificationType: null,
                source: "cline-sdk",
            },
        });
        this.emitSummary(errorSummary);
    }
    async dispatchResolvedTaskInput(input) {
        if (this.sessionRuntime.getTaskSessionId(input.taskId)) {
            return {
                result: await this.sessionRuntime.sendTaskSessionInput(input.taskId, input.prompt, input.mode, input.images, input.delivery),
            };
        }
        const persistedSnapshot = await this.sessionRuntime.readPersistedTaskSession(input.taskId);
        const restartedSession = await this.sessionRuntime.restartTaskSession({
            taskId: input.taskId,
            prompt: input.prompt,
            mode: input.mode,
            images: input.images,
            initialMessages: persistedSnapshot?.messages,
        });
        return {
            result: restartedSession.result,
            warnings: restartedSession.warnings,
        };
    }
    async startTaskSession(request) {
        const existing = this.messageRepository.getTaskEntry(request.taskId);
        if (existing && (existing.summary.state === "running" || existing.summary.state === "awaiting_review")) {
            return cloneSummary(existing.summary);
        }
        const providerId = request.providerId?.trim() || "anthropic";
        const modelId = request.modelId?.trim() || "claude-sonnet-4-6";
        const resolvedMode = request.mode ?? "act";
        const persistedResumeSnapshot = request.resumeFromTrash
            ? await this.sessionRuntime.readPersistedTaskSession(request.taskId).catch(() => null)
            : null;
        const entry = request.resumeFromTrash && persistedResumeSnapshot
            ? createTaskEntryFromPersistedSession(request.taskId, persistedResumeSnapshot.messages, {
                state: "awaiting_review",
                mode: resolvedMode,
                workspacePath: request.cwd,
                startedAt: now(),
                lastOutputAt: now(),
                reviewReason: "attention",
            })
            : {
                summary: {
                    ...createDefaultSummary(request.taskId),
                    state: request.resumeFromTrash ? "awaiting_review" : "running",
                    mode: resolvedMode,
                    workspacePath: request.cwd,
                    startedAt: now(),
                    lastOutputAt: now(),
                    reviewReason: request.resumeFromTrash ? "attention" : null,
                },
                messages: [],
                activeAssistantMessageId: null,
                activeReasoningMessageId: null,
                toolMessageIdByToolCallId: new Map(),
                toolInputByToolCallId: new Map(),
            };
        this.messageRepository.setTaskEntry(request.taskId, entry);
        this.pendingTurnCancelTaskIds.delete(request.taskId);
        const normalizedPrompt = request.prompt.trim();
        const hasRequestImages = Boolean(request.images && request.images.length > 0);
        if (!request.resumeFromTrash && (normalizedPrompt.length > 0 || hasRequestImages)) {
            const message = createMessage(request.taskId, "user", normalizedPrompt, request.images);
            entry.messages.push(message);
            this.emitMessage(request.taskId, message);
            const runningSummary = updateSummary(entry, {
                state: "running",
                reviewReason: null,
                lastOutputAt: now(),
                lastHookAt: now(),
                latestHookActivity: {
                    activityText: "Agent active",
                    toolName: null,
                    toolInputSummary: null,
                    finalMessage: null,
                    hookEventName: "turn_start",
                    notificationType: null,
                    source: "cline-sdk",
                },
            });
            this.emitSummary(runningSummary);
        }
        this.emitSummary(entry.summary);
        void (async () => {
            const assistantCountBeforeStart = entry.messages.filter((message) => message.role === "assistant").length;
            try {
                const runtimeSetup = await this.ensureRuntimeSetup(request.cwd);
                const runtimePrompt = runtimeSetup.resolvePrompt(request.prompt);
                let systemPrompt = await resolveClineSdkSystemPrompt({
                    cwd: request.cwd,
                    providerId,
                    rules: runtimeSetup.loadRules(),
                });
                const appendedSystemPrompt = resolveHomeAgentAppendSystemPrompt(request.taskId);
                if (appendedSystemPrompt) {
                    systemPrompt = `${systemPrompt}\n\n${appendedSystemPrompt}`;
                }
                const startResult = await this.sessionRuntime.startTaskSession({
                    taskId: request.taskId,
                    cwd: request.cwd,
                    prompt: runtimePrompt,
                    initialMessages: request.resumeFromTrash ? persistedResumeSnapshot?.messages : undefined,
                    images: request.images,
                    providerId,
                    modelId,
                    mode: resolvedMode,
                    apiKey: request.apiKey,
                    baseUrl: request.baseUrl,
                    systemPrompt,
                    userInstructionWatcher: runtimeSetup.watcher,
                    requestToolApproval: runtimeSetup.requestToolApproval,
                });
                const warningMessage = formatStartWarnings(startResult.warnings);
                if (warningMessage) {
                    this.emitSummary(updateSummary(entry, {
                        warningMessage,
                    }));
                }
                const initialAgentText = readAgentResultText(startResult.result);
                if (initialAgentText) {
                    const assistantCountAfterStart = entry.messages.filter((message) => message.role === "assistant").length;
                    if (assistantCountAfterStart > assistantCountBeforeStart) {
                        return;
                    }
                    const agentMessage = setOrCreateAssistantMessage(entry, request.taskId, initialAgentText) ??
                        createAssistantMessage(entry, request.taskId, initialAgentText);
                    this.emitMessage(request.taskId, agentMessage);
                }
            }
            catch (error) {
                this.emitTaskFailure(request.taskId, entry, "start", error);
            }
        })();
        return cloneSummary(entry.summary);
    }
    async stopTaskSession(taskId) {
        let entry = this.messageRepository.getTaskEntry(taskId);
        if (!entry) {
            // Runtime restarts can clear in-memory task entries while the SDK still has a persisted
            // session for this task. Rebind first so stop() can target that recovered session id.
            const reboundSummary = await this.rebindPersistedTaskSession(taskId);
            if (!reboundSummary) {
                return null;
            }
            entry = this.messageRepository.getTaskEntry(taskId);
            if (!entry) {
                return reboundSummary;
            }
        }
        this.pendingTurnCancelTaskIds.delete(taskId);
        await this.sessionRuntime.stopTaskSession(taskId).catch(() => null);
        if (entry.summary.state === "idle") {
            return cloneSummary(entry.summary);
        }
        const summary = updateSummary(entry, {
            state: "interrupted",
            reviewReason: "interrupted",
            exitCode: null,
            lastOutputAt: now(),
        });
        this.emitSummary(summary);
        return summary;
    }
    async abortTaskSession(taskId) {
        const entry = this.messageRepository.getTaskEntry(taskId);
        if (!entry) {
            return null;
        }
        this.pendingTurnCancelTaskIds.delete(taskId);
        await this.sessionRuntime.abortTaskSession(taskId).catch(() => null);
        const summary = updateSummary(entry, {
            state: "interrupted",
            reviewReason: "interrupted",
            exitCode: null,
            lastOutputAt: now(),
        });
        this.emitSummary(summary);
        return summary;
    }
    async cancelTaskTurn(taskId) {
        const entry = this.messageRepository.getTaskEntry(taskId);
        if (!entry) {
            return null;
        }
        if (entry.summary.state !== "running") {
            return null;
        }
        this.pendingTurnCancelTaskIds.add(taskId);
        await this.sessionRuntime.abortTaskSession(taskId).catch(() => null);
        clearActiveTurnState(entry);
        const summary = updateSummary(entry, {
            state: "idle",
            reviewReason: null,
            exitCode: null,
            lastOutputAt: now(),
            lastHookAt: now(),
            latestHookActivity: {
                activityText: "Turn canceled",
                toolName: null,
                toolInputSummary: null,
                finalMessage: null,
                hookEventName: "turn_canceled",
                notificationType: null,
                source: "cline-sdk",
            },
        });
        this.emitSummary(summary);
        return summary;
    }
    async sendTaskSessionInput(taskId, text, mode, images) {
        const entry = this.messageRepository.getTaskEntry(taskId);
        if (!entry) {
            return null;
        }
        if (entry.summary.state !== "running" &&
            entry.summary.state !== "awaiting_review" &&
            entry.summary.state !== "idle" &&
            entry.summary.state !== "failed") {
            return null;
        }
        this.pendingTurnCancelTaskIds.delete(taskId);
        const normalized = text.trim();
        const hasImages = Boolean(images && images.length > 0);
        const effectiveMode = mode ?? entry.summary.mode ?? "act";
        if (normalized.length === 0 && !hasImages) {
            return null;
        }
        {
            const message = createMessage(taskId, "user", normalized, images);
            entry.messages.push(message);
            this.emitMessage(taskId, message);
            clearActiveTurnState(entry);
            const queueDelivery = entry.summary.state === "running";
            const waitingSummary = updateSummary(entry, {
                state: "running",
                mode: effectiveMode,
                reviewReason: null,
                warningMessage: null,
                lastOutputAt: now(),
                lastHookAt: now(),
                latestHookActivity: {
                    activityText: "Agent active",
                    toolName: null,
                    toolInputSummary: null,
                    finalMessage: null,
                    hookEventName: "turn_start",
                    notificationType: null,
                    source: "cline-sdk",
                },
            });
            this.emitSummary(waitingSummary);
            const assistantCountBeforeSend = entry.messages.filter((message) => message.role === "assistant").length;
            void this.ensureRuntimeSetup(entry.summary.workspacePath ?? "")
                .then(async (runtimeSetup) => {
                return await this.dispatchResolvedTaskInput({
                    taskId,
                    prompt: runtimeSetup.resolvePrompt(normalized),
                    mode: effectiveMode,
                    images,
                    delivery: queueDelivery ? "queue" : undefined,
                });
            })
                .then(({ result, warnings }) => {
                const warningMessage = formatStartWarnings(warnings);
                if (warningMessage) {
                    this.emitSummary(updateSummary(entry, {
                        warningMessage,
                    }));
                }
                const agentText = readAgentResultText(result);
                if (agentText) {
                    const assistantCountAfterSend = entry.messages.filter((message) => message.role === "assistant").length;
                    if (assistantCountAfterSend > assistantCountBeforeSend) {
                        return;
                    }
                    const agentMessage = setOrCreateAssistantMessage(entry, taskId, agentText) ??
                        createAssistantMessage(entry, taskId, agentText);
                    this.emitMessage(taskId, agentMessage);
                }
            })
                .catch((error) => {
                this.emitTaskFailure(taskId, entry, "send", error);
            });
        }
        const summary = updateSummary(entry, {
            state: "running",
            mode: effectiveMode,
            reviewReason: null,
            lastOutputAt: now(),
        });
        this.emitSummary(summary);
        return summary;
    }
    async rebindPersistedTaskSession(taskId) {
        const existingEntry = this.messageRepository.getTaskEntry(taskId);
        if (existingEntry && existingEntry.summary.state !== "failed") {
            return cloneSummary(existingEntry.summary);
        }
        const snapshot = await this.sessionRuntime.resumeTaskSession(taskId);
        if (!snapshot) {
            return existingEntry ? cloneSummary(existingEntry.summary) : null;
        }
        const startedAt = Date.parse(snapshot.record.startedAt);
        const updatedAt = Date.parse(snapshot.record.updatedAt || snapshot.record.startedAt);
        const persistedCwd = typeof snapshot.record.cwd === "string" ? snapshot.record.cwd.trim() : "";
        const persistedWorkspaceRoot = typeof snapshot.record.workspaceRoot === "string" ? snapshot.record.workspaceRoot.trim() : "";
        const reboundState = existingEntry?.summary.state === "failed" ? "failed" : "awaiting_review";
        const reboundReviewReason = existingEntry?.summary.state === "failed" ? "error" : "attention";
        const entry = createTaskEntryFromPersistedSession(taskId, snapshot.messages, {
            agentId: "cline",
            state: reboundState,
            mode: existingEntry?.summary.mode ?? null,
            reviewReason: reboundReviewReason,
            workspacePath: persistedCwd || persistedWorkspaceRoot || null,
            startedAt: Number.isFinite(startedAt) ? startedAt : null,
            lastOutputAt: Number.isFinite(updatedAt) ? updatedAt : null,
            warningMessage: existingEntry?.summary.warningMessage ?? null,
            latestHookActivity: existingEntry?.summary.latestHookActivity ?? null,
            latestTurnCheckpoint: existingEntry?.summary.latestTurnCheckpoint ?? null,
            previousTurnCheckpoint: existingEntry?.summary.previousTurnCheckpoint ?? null,
        });
        this.messageRepository.setTaskEntry(taskId, entry);
        return cloneSummary(entry.summary);
    }
    getSummary(taskId) {
        return this.messageRepository.getSummary(taskId);
    }
    listSummaries() {
        return this.messageRepository.listSummaries();
    }
    listMessages(taskId) {
        return this.messageRepository.listMessages(taskId);
    }
    async loadTaskSessionMessages(taskId) {
        return await this.messageRepository.hydrateTaskMessages(taskId, async () => {
            return await this.sessionRuntime.readPersistedTaskSession(taskId);
        });
    }
    applyTurnCheckpoint(taskId, checkpoint) {
        const summary = this.messageRepository.applyTurnCheckpoint(taskId, checkpoint);
        if (!summary) {
            return null;
        }
        this.emitSummary(summary);
        return summary;
    }
    async dispose() {
        await this.sessionRuntime.dispose();
        this.pendingTurnCancelTaskIds.clear();
        for (const setupPromise of this.runtimeSetupByWorkspacePath.values()) {
            try {
                const setup = await setupPromise;
                await setup.dispose();
            }
            catch {
                // Ignore runtime setup disposal failures.
            }
        }
        this.runtimeSetupByWorkspacePath.clear();
        this.messageRepository.dispose();
    }
    emitSummary(summary) {
        this.messageRepository.emitSummary(summary);
    }
    emitMessage(taskId, message) {
        this.messageRepository.emitMessage(taskId, message);
    }
    shouldCaptureReviewCheckpoint(previousSummary, nextSummary) {
        if (!nextSummary) {
            return false;
        }
        if (isHomeAgentSessionId(nextSummary.taskId) || !nextSummary.workspacePath) {
            return false;
        }
        return previousSummary.state !== "awaiting_review" && nextSummary.state === "awaiting_review";
    }
    captureReviewCheckpoint(taskId, summary) {
        const nextTurn = (summary.latestTurnCheckpoint?.turn ?? 0) + 1;
        const staleRef = summary.previousTurnCheckpoint?.ref ?? null;
        void captureTaskTurnCheckpoint({
            cwd: summary.workspacePath ?? ".",
            taskId,
            turn: nextTurn,
        })
            .then((checkpoint) => {
            this.applyTurnCheckpoint(taskId, checkpoint);
            if (!staleRef) {
                return;
            }
            void deleteTaskTurnCheckpointRef({
                cwd: summary.workspacePath ?? ".",
                ref: staleRef,
            }).catch(() => {
                // Best effort cleanup only.
            });
        })
            .catch(() => {
            // Best effort checkpointing only.
        });
    }
    async ensureRuntimeSetup(workspacePath) {
        const normalizedWorkspacePath = workspacePath.trim();
        let setupPromise = this.runtimeSetupByWorkspacePath.get(normalizedWorkspacePath);
        if (!setupPromise) {
            setupPromise = this.createRuntimeSetup(normalizedWorkspacePath);
            this.runtimeSetupByWorkspacePath.set(normalizedWorkspacePath, setupPromise);
        }
        return await setupPromise;
    }
    handleTaskEvent(taskId, event) {
        const entry = this.messageRepository.getTaskEntry(taskId);
        if (!entry) {
            return;
        }
        const previousSummary = cloneSummary(entry.summary);
        let latestSummary = null;
        applyClineSessionEvent({
            event,
            taskId,
            entry,
            pendingTurnCancelTaskIds: this.pendingTurnCancelTaskIds,
            emitSummary: (summary) => {
                latestSummary = summary;
                this.emitSummary(summary);
            },
            emitMessage: (taskIdFromEvent, message) => {
                this.emitMessage(taskIdFromEvent, message);
            },
        });
        if (this.shouldCaptureReviewCheckpoint(previousSummary, latestSummary)) {
            this.captureReviewCheckpoint(taskId, latestSummary);
        }
    }
}
export function createInMemoryClineTaskSessionService(options = {}) {
    return new InMemoryClineTaskSessionService(options);
}
//# sourceMappingURL=cline-task-session-service.js.map
//# debugId=4e409993-3fea-5c84-979b-3a831de5c01f
