
!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]="65c08df1-9d9f-5f3f-b86c-f5e126dde0f9")}catch(e){}}();
import { RELATED_TASK_META_KEY } from '../const.js';
// The console uses const MIN_OBSERVER_INTERVAL_MILLIS = 3000 so it should be fine.
// Exported for tests to keep fake-timer advances in sync with the production interval.
export const PROGRESS_NOTIFICATION_INTERVAL_MS = 3000; // 3 seconds
const TERMINAL_RUN_STATUSES = new Set(['SUCCEEDED', 'FAILED', 'ABORTED', 'TIMED-OUT']);
/**
 * Leads with the run status so clients can see lifecycle transitions
 * (RUNNING → SUCCEEDED) and never miss a terminal flip behind a stale statusMessage.
 * At terminal status the message is only appended when the actor explicitly marked it
 * terminal — otherwise it's an in-progress message left over from before the flip.
 */
export function formatRunStatusMessage(actorName, run) {
    const isTerminal = TERMINAL_RUN_STATUSES.has(run.status);
    const showStatusMessage = run.statusMessage && (!isTerminal || run.isStatusMessageTerminal === true);
    return showStatusMessage
        ? `${actorName}: ${run.status} — ${run.statusMessage}`
        : `${actorName}: ${run.status}`;
}
export class ProgressTracker {
    constructor(options) {
        Object.defineProperty(this, "progressToken", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "sendNotification", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "currentProgress", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: 0
        });
        Object.defineProperty(this, "intervalId", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "stopped", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: false
        });
        Object.defineProperty(this, "lastEmittedMessage", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "taskId", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "onStatusMessage", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        this.progressToken = options.progressToken;
        this.sendNotification = options.sendNotification;
        this.taskId = options.taskId;
        this.onStatusMessage = options.onStatusMessage;
    }
    async updateProgress(message) {
        // Dedup consecutive identical messages so a polling tick that emitted the
        // terminal status doesn't double-emit when the caller also explicitly emits.
        if (message !== undefined && message === this.lastEmittedMessage) {
            return;
        }
        this.lastEmittedMessage = message;
        this.currentProgress += 1;
        // Send progress notification only if progressToken and sendNotification are available
        if (this.progressToken !== undefined && this.progressToken !== null && this.sendNotification) {
            try {
                const notification = {
                    method: 'notifications/progress',
                    params: {
                        progressToken: this.progressToken,
                        progress: this.currentProgress,
                        ...(message && { message }),
                    },
                    // Per MCP spec: progress notifications during task execution should include related-task metadata
                    ...(this.taskId && {
                        _meta: {
                            [RELATED_TASK_META_KEY]: {
                                taskId: this.taskId,
                            },
                        },
                    }),
                };
                await this.sendNotification(notification);
            }
            catch {
                // Silent fail - don't break execution
            }
        }
        // Update task statusMessage if callback is provided
        if (this.onStatusMessage && message) {
            try {
                await this.onStatusMessage(message);
            }
            catch {
                // Silent fail - don't break execution
            }
        }
    }
    startActorRunUpdates(runId, apifyClient, actorName, initial) {
        var _a;
        this.stop();
        this.stopped = false;
        let lastStatus = (_a = initial === null || initial === void 0 ? void 0 : initial.status) !== null && _a !== void 0 ? _a : '';
        let lastStatusMessage = (initial === null || initial === void 0 ? void 0 : initial.statusMessage) || '';
        let tickInProgress = false;
        this.intervalId = setInterval(async () => {
            // Skip if a previous tick is still awaiting run.get() / updateProgress() — otherwise
            // a slow tick can overlap with the next one and cause out-of-order emissions.
            if (tickInProgress)
                return;
            tickInProgress = true;
            try {
                const run = await apifyClient.run(runId).get();
                // stop() may have been called while run.get() was awaiting; clearInterval can't
                // abort an in-flight tick, so guard here to avoid a late duplicate emission.
                if (this.stopped || !run)
                    return;
                const { status, statusMessage } = run;
                const normalizedStatusMessage = statusMessage || '';
                // Only send notification if status or statusMessage changed
                if (status !== lastStatus || normalizedStatusMessage !== lastStatusMessage) {
                    lastStatus = status;
                    lastStatusMessage = normalizedStatusMessage;
                    await this.updateProgress(formatRunStatusMessage(actorName, run));
                    // Stop polling if Actor finished
                    if (TERMINAL_RUN_STATUSES.has(status)) {
                        this.stop();
                    }
                }
            }
            catch {
                // Silent fail - continue polling
            }
            finally {
                tickInProgress = false;
            }
        }, PROGRESS_NOTIFICATION_INTERVAL_MS);
    }
    stop() {
        this.stopped = true;
        if (this.intervalId) {
            clearInterval(this.intervalId);
            this.intervalId = undefined;
        }
    }
}
export function createProgressTracker(progressToken, sendNotification, taskId, onStatusMessage) {
    // Create tracker if we have either progress notification support or a status message callback
    const hasProgressNotificationSupport = progressToken !== undefined && progressToken !== null && !!sendNotification;
    if (!hasProgressNotificationSupport && !onStatusMessage) {
        return null;
    }
    return new ProgressTracker({ progressToken, sendNotification, taskId, onStatusMessage });
}
//# sourceMappingURL=progress.js.map
//# debugId=65c08df1-9d9f-5f3f-b86c-f5e126dde0f9
