/**
 * Poll Sentinel buffer during blocking agent.execute().
 * Does not abort the agent process — returns/rejects as soon as the run is marked killed.
 */

import { formatSentinelKillError } from '../security/sentinel-run-failure.js';

export const SENTINEL_KILL_CHECK_INTERVAL_MS = 250;

export type SentinelRunStatusSnapshot = {
  status?: string;
  killReason?: string;
};

/**
 * Race execute() against periodic Sentinel kill checks.
 * Agent work may continue in the background until the executor finishes.
 */
export async function executeWithSentinelWatch<T>(
  runId: string,
  execute: () => Promise<T>,
  getRunStatus: (runId: string) => SentinelRunStatusSnapshot | undefined
): Promise<T> {
  let timer: ReturnType<typeof setInterval> | undefined;

  const watchPromise = new Promise<never>((_, reject) => {
    timer = setInterval(() => {
      const state = getRunStatus(runId);
      if (state?.status === 'killed') {
        reject(new Error(formatSentinelKillError(state.killReason ?? 'unknown')));
      }
    }, SENTINEL_KILL_CHECK_INTERVAL_MS);
  });

  try {
    return await Promise.race([execute(), watchPromise]);
  } finally {
    if (timer !== undefined) {
      clearInterval(timer);
    }
  }
}
